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

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;
	
}


你可能感兴趣的:(POJ-3974-Palindrome- Manacher 马拉车算法(On寻找最长回文串))