解析:
最长回文子串的通常方法为枚举子串的中心位置,然后再从1开始依次枚举这个子串的长度,当不满足回文串的定义时则结束并继续尝试下一个中心位置,最后找到最大值
上述方法是从1开始枚举子串的长度,利用Manacher算法可以简化枚举子串长度的时间,
设以第i个字符为中心的回文子串半径为f(i),先对原串进行处理,在任意两个相邻的自负之间加入一个字符‘#’(串的两头也要加入),将字符串的长度变为奇数,为了更方便的计算在头部加入一个与其它字符均不相同的字符‘*’,如:字符串“abababa"则变成了”*#a#b#a#b#a#b#a#“,显然可以知道变化后的字符串的最大回文子串长度减1则为原串的最长回文子串长度,先找出一个字符设其位置为id使得id+f(id)>i,则有s[i]==s[2*id-i],以2*id-i为中心的回文子串半径为f(2*id-i),则对于f(i)可得到一个最小值为min(f(2*id-i),f(id)+id-i),为了简化则只需计算每次的最大值i+f(i)即可
#include<iostream>
#include<string>
using namespace std;
int f[2000005];
int main()
{
int n; cin>>n;
while(n--){
string s1; cin>>s1;
string s2;
s2+='*'; s2+='#';
for(int i=0;i<s1.size();++i){s2+=s1[i]; s2+='#';}
for(int i=0;i<s2.size();++i) f[i]=1;
int id=0,ans=0;
for(int i=2;i<s2.size();++i){
if(f[id]+id>i) f[i]=min(f[2*id-i],f[id]+id-i);
else f[i]=1;
while(s2[i-f[i]]==s2[i+f[i]]) ++f[i];
if(i+f[i]>id+f[id]) id=i;
ans=max(ans,f[i]);
}
cout<<ans-1<<endl;
}
}