首页 > 其他 > 详细

P4287 [SHOI2011]双倍回文

时间:2019-12-19 20:49:45      阅读:80      评论:0      收藏:0      [点我收藏+]

题意

考虑对每个节点$x$维护$lastpos_x$表示$x$的所有后缀回文串中第一个$len\leqslant len_x/2$并且能和$x$最后一个字符匹配的,之后枚举节点,判断该点回文串是否合法。

求$lastpos_x$:
如果新建节点$x$满足$len_x\leqslant 2$,那么$lastpos_x=fail_x$。
不然则从$x$的父亲节点向上跳,边跳边判断即可。

code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=500010;
int n,ans;
char s[maxn];
struct PA
{
	int last,tot;
	int fail[maxn],len[maxn],lastpos[maxn];
	int ch[maxn][30];
	PA(){tot=1;fail[0]=1;len[1]=-1;}
	inline int getfail(int x,int pos,char* s)
	{
		s[0]=‘#‘;
		while(s[pos-len[x]-1]!=s[pos])x=fail[x];
		return x;
	}
	inline void build(char* s,int n)
	{
		s[0]=‘#‘;
		for(int i=1;i<=n;i++)
		{
			int c=s[i]-‘a‘;
			int p=getfail(last,i,s);
			if(!ch[p][c])
			{
				int q=++tot;len[q]=len[p]+2;
				int tmp=getfail(fail[p],i,s);
				fail[q]=ch[tmp][c];ch[p][c]=q;
				if(len[q]<=2)lastpos[q]=fail[q];
				else
				{
					tmp=lastpos[p];
					while(s[i-len[tmp]-1]!=s[i]||((len[tmp]+2)<<1)>len[q])tmp=fail[tmp];
					lastpos[q]=ch[tmp][c];
				}
			}
			last=ch[p][c];
		}
	}
}pa;
int main()
{
	//freopen("test.in","r",stdin);
	//freopen("test.out","w",stdout);
	scanf("%d%s",&n,s+1);
	pa.build(s,n);
	for(int i=2;i<=pa.tot;i++)
		if((pa.len[pa.lastpos[i]]<<1)==pa.len[i]&&pa.len[pa.lastpos[i]]%2==0)
			ans=max(ans,pa.len[i]);
	printf("%d",ans);
	return 0;
}

P4287 [SHOI2011]双倍回文

原文:https://www.cnblogs.com/nofind/p/12069513.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!