一般来说求回文串用hash或者后缀数组,但后缀数组是O(nlog(n)),hash比较麻烦,所以我们可以换一种O(n)的求回文串的算法。
对于回文串一般来说会有奇数和偶数之分,但是我们可以把串的头尾加上#号再把每个字符串之间加上#号,然后求每个点以它为中心的最长半径,对于偶数会问它的中心是#。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
char d[200000],c[300000];
int p[300000],r[300005];//半径长度
void mancher(int n){
int i,j,id,mx;
r[0]=1;
mx=0;
id=0;
for(i=1;i<=2*n;i++){
if(i>=mx) r[i]=1;
else {
r[i]=min(r[id-(i-id)],mx-i);
}
while(i-r[i]>=0&&i+r[i]<=2*n&&c[i-r[i]]==c[i+r[i]]) r[i]++;
if(mx<r[i]+i){
mx=r[i]+i;
id=i;
}
}
}
int main()
{
int i,j,n,p,id,re;
while(scanf("%s",d)!=EOF){
n=strlen(d);
c[0]='#';
for(i=1;i<=n;i++){
c[2*i-1]=d[i-1];
c[2*i]='#';
}
mancher(n);
p=1;
for(i=1;i<=2*n;i++){
p=max(p,r[i]-1);
}
printf("%d\n",p);
}
}
推荐题:hdu3068、hdu5157