【BZOJ2342】【SHOI2012】—双倍回文(Pam)

传送门

我们发现一个串和其倒置拼一起也是一个回文串
SSRSSRSS^RSS^R也是一个回文串
考虑维护一个half[k]half[k]指针表示和点kk相同分界点的最长的长度len[k]2\le \frac {len[k]}{2}的点

发现这个也可以在构建PamPam的时候顺便维护

然后枚举所有len[half[k]]2==len[k]len[half[k]]*2==len[k]的点取maxmax即可

#include<bits/stdc++.h>
using namespace std;
#define gc getchar
inline int read(){
	char ch=gc();
	int res=0,f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
	return f?res:-res;
}
#define re register
#define pii pair<int,int>
#define pb push_back
#define fi first
#define se second
#define cs const
#define ll long long
const int N=500005;
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
int ans;
char s[N];
namespace Pam{
	int nxt[N][26],fail[N],len[N],half[N];
	int tot,last;
	inline void init(){
		fail[0]=1,len[1]=-1,tot++;
	}
	inline void insert(int c,int i){
		int p=last;
		while(s[i-len[p]-1]!=s[i])p=fail[p];
		if(!nxt[p][c]){
			len[++tot]=len[p]+2;
			int k=fail[p];
			while(s[i-len[k]-1]!=s[i])k=fail[k];
			fail[tot]=nxt[k][c],nxt[p][c]=tot;
			k=half[p];
			while(s[i]!=s[i-len[k]-1])k=fail[k];
			k=nxt[k][c];
			while(len[k]*2>len[tot])k=fail[k];
			half[tot]=k;
			if((len[tot]%4==0)&&(len[k]*2==len[tot]))chemx(ans,len[tot]);
		}
		last=nxt[p][c];
	}
}
int main(){
	int len=read();
	scanf("%s",s+1),s[0]='$';
	Pam::init();
	for(int i=1;i<=len;i++)Pam::insert(s[i]-'a',i);
	cout<<ans;
}
posted @ 2019-07-22 11:52  Stargazer_cykoi  阅读(93)  评论(0编辑  收藏  举报