public static String getLongestPalindrome(String s){
        char[] T = preProcess(s).toCharArray();

        int n = T.length;
        int[] P = new int[n];

        int C = 0, R = 0;

        for (int i = 1; i < n-1; i++) {
            int i_mirror = 2*C - i; // equals to i' = C - (i-C)

            if ( i < R ) {
                P[i] = Math.min(R-i, P[i_mirror]);
            } else{
                P[i] = 0;
            }

            // Attempt to expand palindrome centered at i
            while( T[i+1+P[i]] == T[i-1-P[i]] )
                P[i]++;

            // if palindrome centered at i expand past R
            // adjust center based on expanded palindrome

            if ( debug ) {
                System.out.println("i="+i +", P[i]="+P[i] + ", R="+R);
            }

            if ( i + P[i] > R) {
                C = i;
                R = i + P[i];

                if ( debug ){
                    System.out.println("Updated C="+C +", R="+R);
                }
            }



        }

        int maxLen = 0;
        int centerIndex = 0;
        for (int i = 1; i < n-1 ; i++) {
            if (P[i] >  maxLen) {
                maxLen = P[i];
                centerIndex = i;
            }
        }
        if ( debug ){
            System.out.println("centerIndex: " + centerIndex);
            System.out.println("maxLen: " + maxLen);
        }

        int beginIndex = (centerIndex-1-maxLen)/2;

        return s.substring(beginIndex, beginIndex+maxLen);

    }