功能:O(n)时间内计算最长回文子串的长度;
操作:先在每两个相邻字符中间插入一个分隔符,分隔符要在原串中没有出现过(一般用‘#’分隔);P[i]记录以字符str[i]为中心的最长回文串,即str[i-p[i],i-1] == str[i+1,i+p[i]],则P[i]-1就是该回文子串在原串中的长度;求出p[i],即可知道最大回文子串长度;
思路:为什么能使时间复杂度为O(n*n)的问题,变为O(n)的问题?是因为计算时避免无用的比较,用前面的值得到现在的值;用mx记在i之前的回文串中,延伸至最右端的位置,同时用id这个变量记下取得这个最优mx时的id值。有以下两种可能情况:
即p[i]=min( p[2*id-i], mx-i);
代码:
void Manacher(char str1[],int len){
//初始化
char str[2*len+1];
int cnt = 0;
str[cnt++] = '#';
for(int i =0;i<len;i++){
str[cnt++] = str1[i];
str[cnt++] = '#';
}
//求p[i]
int i;
int mx = 0;
int id;
for(i=0; i<2*len+1; i++)
{
if( mx > i )
p[i] = min( p[2*id-i], mx-i );
else
p[i] = 1;
for(;i-p[i]>=0&&str[i+p[i]] == str[i-p[i]]; p[i]++);
if( p[i] + i > mx )
{
mx = p[i] + i;
id = i;
}
}
}