回文字符串123321
回文直径:6
回文半径:3

求一个字符串中的最长回文字符串. abc123321def
一般会在原字符串中添加特殊字符,比如添加"#".
变成#a#b#c#1#2#3#3#2#1#d#e#f#

常考数据结构与算法-manacher算法_回文字符串

public class Code_Manacher {
    public static void main(String[] args) {
        System.out.println(manacher("a"));
    }

    // 求回文串的长度
    public static int manacher(String s){
        if(null == s || s.length() == 0){
            return 0;
        }

        // "abcde"  ->  "#a#b#c#d#e#"
        char[] str = manacherString(s);
        // 回文半径的大小
        int[] pArr = new int[str.length];
        int C = -1;
        int R = -1; // 最右的扩成功位置,再下一个位置
        int max = Integer.MIN_VALUE;
        int end = 0;
        for (int i = 0; i < str.length; i++) {
            pArr[i] = R > i ? Math.min(pArr[2*C-i],R-i) :1;

            while(i+pArr[i]<str.length && i-pArr[i]>-1)
            {
                // 向两边扩展
                 if(str[i+pArr[i]] == str[i-pArr[i]]){
                     pArr[i]++;
                 }else{
                     break;
                 }
            }

            // R被扩展
            if(i+pArr[i]>R){
                R = i+pArr[i];
                C = i;
            }

            //max = Math.max(max,pArr[i]);
            if(max < pArr[i]){
                max = pArr[i];
                end = R/2-1; // 记录最长回文字符结束的位置
            }
        }
//        for (int i = 0; i < str.length; i++) {
//            System.out.printf("%c",str[i]);
//        }


        System.out.println(end);
        for (int i = end+2-max; i <=end ; i++) {
            System.out.printf("%c",s.charAt(i)); // 打印出回文字符串
        }
        System.out.println();
        return max-1; // 减去回文串中的最后一个#
    }

    public static char[] manacherString(String s){
        char[] str = new char[2*s.length()+1];
        str[0]='#';
        int j = 1;
        for (int i = 0; i < s.length(); i++) {
            str[j++] = s.charAt(i);
            str[j++] = '#';
        }
        return str;
    }
}