//使用manacher算法
//首先将字符串 扩成#a#b#c#... 这样就可以消除 奇数偶数的问题
//通过 最大半径和中心值 找到最长回文
//其中 有一个至少不用比较的区域 然后再通过这个区域 慢慢像两边扩
//至少不用比较的区域:通过是否落在之前R范围内来判断
//1、当i落在R之外,不用比较的就只有自己本身了
//2、当i落在R里,那就是与i对称 ii的不用比较区域
//3、当i落在R上,就是i到R的距离,作为不用比较区域
//不断更新半径和中心值
class Solution {
//使用manacher算法
//首先将字符串 扩成#a#b#c#... 这样就可以消除 奇数偶数的问题
//通过 最大半径和中心值 找到最长回文
//其中 有一个至少不用比较的区域 然后再通过这个区域 慢慢像两边扩
//至少不用比较的区域:通过是否落在之前R范围内来判断
//1、当i落在R之外,不用比较的就只有自己本身了
//2、当i落在R里,那就是与i对称 ii的不用比较区域
//3、当i落在R上,就是i到R的距离,作为不用比较区域
//不断更新半径和中心值
public String longestPalindrome(String s) {
if(s.length()==0||s.length()==1){
return s;
}
return lenPalindrome(s).replace("#", "");
}
public static String changeString(String s){
String str="#";
for(int i=0;i<s.length();i++){
str+=s.charAt(i)+"#";
}
return str;
}
public static String lenPalindrome(String s){//最大回文长度
String str=changeString(s);
///记录至少不用比较的区域 的值(每一个点的半径)
int []nArea=new int[str.length()];
int R=-1;//最大半径
int C=-1;//中心点
// int max=-1;//找到向外扩最大的值
for(int i=0;i<str.length();i++){
///每个点对应的至少不用比较区域(最小半径)
nArea[i]=R>i ? Math.min(nArea[2*C-i],R-i):1;
///填入值 半径边界问题
while(i+nArea[i]<str.length()&&i-nArea[i]>-1){
if(str.charAt(i+nArea[i])==str.charAt(i-nArea[i])){//如果半径 左右的值相同, 最大不用比较区域的值++ 然后需要和之前的R比较
nArea[i]++;
}else{
break;
}///这个循环结束 也就是 找到了这个点向外扩的最大值
需要找到所有点中最大半径 和对应的C
if(i+nArea[i]>R){
R=nArea[i]+i;
C=i;
}
// max=Math.max(max,nArea[i]);//记录了向外扩的最大值
}
由于 这个字符串是之前处理过的,有个规律就是 处理前的最大长度 就是往外扩最大值-1
}
///由于需要返回字符串,因为nArea 里面记录每一个点往外扩的最大值 需要找到最大值 和当时的点
int m=-1;
int start=-1;
for(int k=0;k<nArea.length;k++){
if(m<nArea[k]){
start=k;
m=nArea[k];
}
}///返回开始的中心点 和往外扩的最大值
return str.substring(start-m+1,start+m);
}
}