您的位置:首页 > 其它

POJ-3974-Palindrome- Manacher 马拉车算法(On寻找最长回文串)

2016-01-08 09:51 375 查看
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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: