BZOJ 2565 最长双回文串

题目链接:最长双回文串

  回文自动机第三题。

  正反各构一个回文自动机,就可以得到以每个位置开头和结尾的最长回文串了。

  然后枚举一下断点就做完了。

  下面贴代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 500010

using namespace std;
typedef long long llg;

char a[maxn]; int ans;
struct PAM{
	int l[maxn],s[maxn][26],f[maxn];
	int tt,la,ans,dt,g[maxn];
	PAM(){f[0]=1,l[++tt]=-1;}
	void add(int c,int n){
		int p=la;
		while(a[n-l[p]-1]!=a[n]) p=f[p];
		if(!s[p][c]){
			int np=++tt,k=f[p]; l[np]=l[p]+2;
			while(a[n-l[k]-1]!=a[n]) k=f[k];
			f[np]=s[k][c]; s[p][c]=np;
		}
		la=s[p][c]; g[n]=l[la];
	}
}A,B;

int main(){
	File("a");
	scanf("%s",a+1);int n=strlen(a+1);
	for(int i=1;i<=n;i++) A.add(a[i]-'a',i);
	reverse(a+1,a+n+1);
	for(int i=1;i<=n;i++) B.add(a[i]-'a',i);
	for(int i=1;i<n;i++) ans=max(ans,A.g[i]+B.g[n-i]);
	printf("%d",ans);
	return 0;
}
posted @ 2017-03-10 11:06  lcf2000  阅读(152)  评论(1编辑  收藏  举报