O(n)效率的字符串求最长回文串,感觉这个blog上写的很详细:http://www.open-open.com/lib/view/open1419150233417.html
有几个要点:
1、先要将字符串扩展成2*l+1长度的,在每两个字符之间要加上一个用不到的字符,比如‘#’,方便处理偶数回文串。
2、在扩展后的字符串两端要加一些特殊字符,防越界。
3、ra[i]数组表示以i为中点的最长回文串,mx表示以j(1<=j<i)为中心的回文串所能达到的在该字符串中的位置,po来记录达到最远位置的回文串的中心位置。
(证明ra[i]-1即为原字符串的回文串的长度的证明:http://wenku.baidu.com/view/3031d2d3360cba1aa811da42.html)
代码附上
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=1000012;
char s[maxn];
char tmp[maxn<<1];
int ra[maxn<<1];
int INIT(char *st)
{
int i,len=strlen(st);
tmp[0]='@';
for (i=1;i<=2*len;i+=2)
{
tmp[i]='#';
tmp[i+1]=st[i/2];
}
tmp[2*len+1]='#';
tmp[2*len+2]='$';
tmp[2*len+3]=0;
return 2*len+1;
}
int MANACHER(char *st,int len)
{
int mx=0,ans=0,po=0;
for (int i=1;i<=len;i++)
{
if (mx>i)
ra[i]=min(mx-i,ra[2*po-i]);
else ra[i]=1;
while (st[i-ra[i]]==st[i+ra[i]]) ra[i]++;
if (ra[i]+i>mx)
{
mx=ra[i]+i;
po=i;
}
ans=max(ans,ra[i]);
}
return ans-1;
}
int main()
{
int T;
scanf("%d",&T);
getchar();
while (T--)
{
int ans,l;
gets(s);
l=INIT(s);
printf("%d\n",MANACHER(tmp,l));
}
return 0;
}
可以去hihoCoder 1032交:https://hihocoder.com/problemset/problem/1032