/*最长回文子串(Manacher算法 马拉车算法-_-)
马拉车算法需要计算以每个字符为中心的回文串半径。并记录最右边界
马拉车算法基于这样一个事实,从回文串的中心到两边是对称的,意味着以两边对称的字符为中心的回文串半径相等(在不超过最右边界的情况下,如果超出就需要扩展搜索)
*/
public String longestPalindrome(String s) {
//构造一下s,字母间加上'#',abc变为#a#b#c#
StringBuffer sb = new StringBuffer();
sb.append('#');
for(int i=0; i<s.length(); ++i){
sb.append(s.charAt(i));
sb.append('#');
}
String str = sb.toString();
int len = str.length();
int center = 0;
int longestPal = 0;
int rightBound = 0;
int rightBoundCenter = 0;
int[] halfArr = new int[len];
for(int i=0; i<len; ++i){
boolean needCalc = true;
if(rightBound>i){
int leftCenter = rightBoundCenter * 2 - i; //根据右边界中心计算出i的对称点
halfArr[i] = halfArr[leftCenter];
//判断是否需要扩展
if(i+halfArr[i] > rightBound){
halfArr[i] = rightBound - i;
}
//比边界小,不用扩展了
if(i + halfArr[leftCenter]<rightBound)
needCalc = false;
}
if(needCalc){
int left = i - halfArr[i] - 1;
int right = i + halfArr[i] + 1;
while (left>=0 && right<len && str.charAt(left)==str.charAt(right)){
--left;
++right;
++halfArr[i];
}
rightBound = i + halfArr[i];
rightBoundCenter = i;
if(halfArr[i]>longestPal){
center = i;
longestPal = halfArr[i];
}
}
}
StringBuffer rsb = new StringBuffer();
//两头肯定是'#',需要把#号给干掉
for(int i=center-longestPal+1; i<=center+longestPal; i += 2){
rsb.append(str.charAt(i));
}
String palindrome = rsb.toString();
return palindrome;
}