最长回文 HDU - 3068(马拉车(Manacher)算法-最长回文子串)

 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
回文就是正反读都是一样的字符串,如aba, abba等 

Input
输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c…y,z组成的字符串S
两组case之间由空行隔开(该空行不用处理)
字符串长度len <= 110000
Output
每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度.
Sample Input

aaaa

abab

Sample Output

4
3

推荐一个大牛博客:https://www.cnblogs.com/grandyang/p/4475985.html
马拉车算法,详情请看代码注释。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#define LL long long
#define PI acos(-1.0)
const int maxn=2e6+100;
const int inf=0x3f3f3f3f;
using namespace std;
char s[maxn],ss[maxn];
int r[maxn];
int Manacher(int n)
{
	int cnt=0;
	ss[cnt++]='$';
	ss[cnt++]='#';
	for(int i=0;i<n;i++)
	{
		ss[cnt++]=s[i];
		ss[cnt++]='#';
	}
	ss[cnt++]='/0';
	int pos=0,rx=0,ans=1;
	//pos:目前回文子串能到最右位置所对应的中心
	//rx:目前回文子串能到的最右位置 	
	for(int i=1;i<cnt;i++)
	{
		r[i]=rx>i?min(r[2*pos-i],rx-i):1;
		//这里设j是i以pos为对称轴时所对应的位置,那么i+j=2*pos。
		//所以,当r[2*pos-i]<rx-i时,r[i]==r[2*pos-i]。 
		
		while(ss[i-r[i]]==ss[i+r[i]]) r[i]++;
		//rx之后的要一个个试。 
		if(rx<i+r[i])
		{
			rx=i+r[i];
			pos=i;
		}
		if(ans<r[i]-1)
		  ans=r[i]-1;
		//ans=max(ans,r[i]-1);	迷之超时。
	}
	return ans;
	
	
}
int main(void)
{
	int flag=0;
    while(~scanf("%s",s))
    {
    	if(flag) getchar();
    	else flag=1;
    	printf("%d\n",Manacher(strlen(s)));	
	}
 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/birdmanqin/article/details/87933768