代码来源:程序员代码面试指南
主要是Manacher算法的使用,具体请参考程序员代码面试指南P483,有很详细的介绍。
题目,来自牛客网:
对于一个字符串,请设计一个高效算法,计算其中最长回文子串的长度。
给定字符串A以及它的长度n,请返回最长回文子串的长度。
测试样例:
"abc1234321ab",12
返回:7
返回:7
代码如下,使用Manacher算法时间复杂度可达到O(N)!
import java.util.*;
public class Palindrome {
//加入特殊字符'#',得到新的字符串
public char[] manacherString(String str){
char[] charArr=str.toCharArray();
char[] res=new char[str.length()*2+1];
int index=0;
for(int i=0;i<res.length;i++){
res[i]=(i&1)==0?'#':charArr[index++];
}
return res;
}
public int getLongestPalindrome(String A, int n) {
// write code here
if(A==null||n<=0)
return 0;
char[] charArr=manacherString(A); //manacher字符串
int[] pArr=new int[charArr.length]; //以charArr[i]为中心的回文子串半径数组
int index=-1;//中心位置
int pR=-1;//当前回文子串最右将达到的位置
int max=Integer.MIN_VALUE;//最小值
for(int i=0;i<charArr.length;i++){//manacher算法核心部分
pArr[i]=pR>i?Math.min(pArr[2*index-i],pR-i):1;
while(i+pArr[i]<charArr.length&&i-pArr[i]>=0){//半径在合理的范围之内
if(charArr[i+pArr[i]]==charArr[i-pArr[i]])
pArr[i]++;
else{
break;
}
}
if(i+pArr[i]>pR){//超过了之前pR的值
pR=i+pArr[i];//更新pR
index=i; //更新index
}
max=Math.max(max,pArr[i]);//得到半径的最大值
}
return max-1;//半径减1就是之前没有加特殊字符'#'的最长回文子串的长度
}
}