---
# System prepended metadata

title: CSES Problem SetLongest Palindrome

---

https://cses.fi/paste/d215266054eda1d466ea03/



```java=
import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;
 
public class CSESLongestPalidrome {
    static PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
 
    static class Reader {
        private BufferedReader br;
        private String content;
        private StringTokenizer st;
 
        public Reader() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }
 
        public boolean hasNext() throws IOException {
            if (st != null && st.hasMoreTokens()) return true;
 
            boolean next = (content = br.readLine()) != null && !content.isEmpty();
            if (next) st = new StringTokenizer(content);
            return next;
        }
 
        public String next() {
            try {
                hasNext();
            } catch (IOException e) {
            }
            return st.nextToken();
        }
    }
 
    static long MOD = (long) (1e9 + 7);
    static int N = (int) (1e7 + 7);
    static long x = 31;
    static long pw[] = new long[N]; // pw[i] = x^i % MDO
    static long ipw[] = new long[N]; // pw[i] = x^i % MDO
    static long v[] = new long[N];
 
    private static void make_hash(String s) { // s is 1-based
        int n = s.length();
 
        for (int i = 1; i < n; i++) {
            v[i] = (s.charAt(i) - 'a' + 1) * pw[i];
        }
        // prefix sum
        for (int i = 1; i < n; i++) {
            v[i] = (v[i - 1] + v[i]) % MOD;
        }
    }
 
    private static void build(String s) {
        pw[0] = 1;
        for (int i = 1; i < N; i++) pw[i] = pw[i - 1] * x % MOD;
 
//        模逆元
//        ipw[0] = 1;
//        ipw[1] = pow(x, MOD - 2, MOD); // x^-1 = x 的 P-2 mod P
//                                       // 費馬小定理
//        for (int i = 1; i < N; i++) ipw[i] = ipw[i - 1] * ipw[1] % MOD;
 
        make_hash(s);
    }
 
    private static boolean query(int l, int r, int l1, int r1) {
//        long h1 = (v[r] - v[l - 1] + MOD) * ipw[l - 1] % MOD; // +MOD 可以確保結果是正數
//        long h2 = (v[r1] - v[l1 - 1] + MOD) * ipw[l1 - 1] % MOD;
        long h1 = (v[r] - v[l - 1] + MOD)% MOD;
        long h2 = (v[r1] - v[l1 - 1] + MOD)% MOD;
        
        return (h1 * pw[l1 - 1] % MOD) == (h2 * pw[l - 1] % MOD);
    }
    private static boolean isPal(int n, int l, int r) {
        // [l, r] is 1-base
        return query(l, r, 2 * n + 1 - r, 2 * n + 1 - l);
    }
 
    public static void main(String[] args) throws IOException {
        Reader reader = new Reader();
        int max = 0;
 
        while (reader.hasNext()) {
            String s = reader.next();
            String tmp = " " + s + reverse(s);
            build(tmp);
 
            int n = s.length();
            int pos = -1;
            for (int i = 1; i <= n; i++) {
                 int l = 1;
                 int r = n;
                 while(l < r){
                     int mid = (l + r) >> 1;
                     if(!isValidPalLength(i, i + mid, n)){
                         r = mid;
                     }else{
                         l = mid + 1;
                     }
                 }
                 if(max < l){
                    max = l;
                    pos = i;
                 }
                
            }
            out.println(tmp.substring(pos, pos + max));
            out.flush();
        }
        
    }
    
    private static boolean isValidPalLength(int l, int r, int n ){
        if(l <= 0 || r > n){
            return false;
        }
        return  isPal(n, l, r) || isPal(n, l, r + 1) ;
    }
 
    private static String reverse(String s) {
        StringBuilder sb = new StringBuilder(s);
        sb.reverse();
        return sb.toString();
    }
}
```
class Solution {
public:
    int maximumScore(vector<int>& W, vector<vector<int>>& edges) {
        int n = W.size();

        using pii = pair<int, int>;
        vector<vector<pii>> adj(n);
        for (vector<int> edge: edges) {
            int u = edge[0], v = edge[1];
            adj[u].push_back({W[v], v});
            adj[v].push_back({W[u], u});
        }
        for (int i = 0; i < n; i++) {
            sort(adj[i].begin(), adj[i].end());
            reverse(adj[i].begin(), adj[i].end());
            if (adj[i].size() > 3) adj[i].resize(3);
        }
        
        int ans = -1;
        for (vector<int> edge: edges) {
            int u = edge[0], v = edge[1];

            for (auto [wx, x] : adj[u]) {
                for (auto [wy, y] : adj[v]) {
                    if (x != y && y != u && x != v) {
                        int val = W[u]+W[v]+W[x]+W[y];
                        ans = max(ans, val);
                    }
                }
            }
        }

        return ans;
    }
};

```