manacher
manacher(马拉车)算法是用于解决O(n)复杂度的情况下求字符串中最长回文串的长度。
首先,统一奇长度回文串和偶长度回文串的处理方式,可以在每两个字符中间插入"#",例如:$aba\Longrightarrow $ # \(a\) # \(b\) # \(a\) #。这样就可以把所有的回文串转化为奇长度回文串。设\(f[i]\)为回文串半径,对于奇长度回文串和偶长度回文串,设原长为\(n\),转换后的回文串长度为\(2n+1\),\(f[i]\times 2-1=2n+1\),所以\(n=f[i]-1\)。
然后假设已知\(id+f[id]=mx\),求\(f[i]\),当\(i<mx\)时,即
\(f[i]=min(f[2\times id-i],mx-i)\)
否则\(f[i]=1\)
再看以i为中心的回文串是否能继续扩大。
最后找出最大值就可以了。
代码:
#include<iostream>
#include<cstring>
using namespace std;
int n;
char a[50000010];
int ans=1;
int f[50000010];
int main(){
scanf("%s",a+1);
n=strlen(a+1);
for(int i=2*n;i>=1;i-=2){
a[i]=a[i/2];
}
for(int i=1;i<=2*n+1;i+=2){
a[i]='#';
}
int mx=0;
int id=0;
for(int i=1;i<=2*n+1;i++){
if(mx>i){
f[i]=min(f[id*2-i],mx-i);
}
else{
f[i]=1;
}
while(a[i+f[i]]==a[i-f[i]]&&i+f[i]<2*n+2&&i-f[i]>0){
f[i]++;
}
ans=max(ans,f[i]-1);
if(i+f[i]>mx){
mx=i+f[i];
id=i;
}
}
cout<<ans;
return 0;
}