http://poj.org/problem?id=3974
马拉车算法的讲解,这个地方讲得很详细:http://www.cnblogs.com/grandyang/p/4475985.html
很简单的又很有威力的一个算法。
实现非常简单
该算法主要步骤就两步:
1、通过加不影响结果的分隔符#,使得不管奇偶串通通变成 奇数串
2、通过利用对称的关系 线性复杂度求得P数组
则最长回文串便是 max_p[i]-1了 (p[i]记录的是以i为中心的最长回文半径,但是由于处理后的数组中存在的#可以证得p[i]-1刚好是 去掉#后的回文串长度)
如果最长回文串的中心为#,表示这是一个偶数串,否则为奇数串
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <vector>
#include <iostream>
using namespace std;
int min(int a,int b){return a<b?a:b;}
char tm[1000000+5];
char t[2000000+5];
int p[2000000+5];
int ok=0;
int Manacher(char *t)
{
int ans_len=1,ans_center=0;
int mx=0,id,i;
for (i=1;i<=ok;i++)
{
if (mx>i)
p[i]=min(p[2*id-i],mx-i);
else
p[i]=1;
while(t[i-p[i]]==t[i+p[i]])
p[i]++;
if (i+p[i]>mx)
{
mx=i+p[i];id=i;
if (p[i]>ans_len)
ans_len=p[i],ans_center=i;
}
}
return ans_len-1;
}
int main()
{
int i,j,k;
int cnt=1;
while(scanf("%s",tm+1)!=EOF)
{
if (strcmp(tm+1,"END")==0) break;
int len=strlen(tm+1);
ok=0;
t[0]='$';
for (i=1;i<=len;i++)
{
t[++ok]='#';
t[++ok]=tm[i];
}
t[++ok]='#';
t[ok+1]=0;
int ans=Manacher(t);
printf("Case %d: %d\n",cnt++,ans);
}
return 0;
}