首页 > 代码库 > bzoj2342 [Shoi2011]双倍回文
bzoj2342 [Shoi2011]双倍回文
Description
Input
输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容。
Output
输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文子串不存在,则输出0。
Sample Input
16
ggabaabaabaaball
ggabaabaabaaball
Sample Output
12
HINT
N<=500000
正解:回文自动机。
一道回文自动机的板子题。。我们直接构造字符串的$PAM$,然后在$fail$树上$dfs$,找到一个长度既是$4$的倍数,祖先中又有长度等于它的一半的字符串就行了。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath>10 #include <queue>11 #include <stack>12 #include <map>13 #include <set>14 #define inf (1<<30)15 #define N (500010)16 #define il inline17 #define RG register18 #define ll long long19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)20 21 using namespace std;22 23 struct edge{ int nt,to; }g[2*N];24 25 int ch[N][26],fa[N],l[N],head[N],cnt[N],n,la,sz,num,ans;26 char s[N];27 28 il int gi(){29 RG int x=0,q=1; RG char ch=getchar();30 while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar();31 if (ch==‘-‘) q=-1,ch=getchar();32 while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar();33 return q*x;34 }35 36 il void insert(RG int from,RG int to){37 g[++num]=(edge){head[from],to},head[from]=num; return;38 }39 40 il void add(RG int c,RG int n){41 RG int x=la; while (s[n-l[x]-1]!=s[n]) x=fa[x];42 if (!ch[x][c]){43 RG int v=++sz,k=fa[x]; l[v]=l[x]+2;44 while (s[n-l[k]-1]!=s[n]) k=fa[k];45 fa[v]=ch[k][c],ch[x][c]=v,insert(fa[v],v);46 }47 la=ch[x][c]; return;48 }49 50 il void dfs(RG int x){51 if (l[x]%4==0 && cnt[l[x]/2]) ans=max(ans,l[x]); ++cnt[l[x]];52 for (RG int i=head[x];i;i=g[i].nt) dfs(g[i].to); --cnt[l[x]]; return;53 }54 55 il void work(){56 n=gi(),scanf("%s",s+1),l[++sz]=-1,fa[0]=1;57 for (RG int i=1;i<=n;++i) add(s[i]-97,i);58 dfs(0),printf("%d\n",ans); return;59 }60 61 int main(){62 File("PAM");63 work();64 return 0;65 }
bzoj2342 [Shoi2011]双倍回文
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。