双倍回文[Shoi2011][bzoj2342]

 

 

双倍回文[Shoi2011][bzoj2342]

 

2342: [Shoi2011]双倍回文

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2820  Solved: 1088
[Submit][Status][Discuss]

Description

 

Input

输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容。

 

Output

输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文子串不存在,则输出0

Sample Input

16
ggabaabaabaaball

Sample Output

12

HINT

 

N<=500000

 

Source

题意就是要求一个回文串,这个回文串的一半也是回文串,那么,可以看出这个串的长度必须是4的倍数。。。。。真心想不出,想了30分钟,并没有做出来,对回文自动机的理解还不是很充分,看了题解,大部分用了马拉车,思维题,但也有充分利用回文自动机的性质;观察回文自动机上的fail链,也就是后缀链,它满足fail链连向的节点是这个节点最长的回文后缀,那么,当整个串都添加进去时,fail链也就成了fail树,连接了所有本质不同的回文串,而且,这个是一个有向的,由小的串往两边添加字符成大的串,所以就可以从根节点0号节点开始dfs,记录一个桶,表示长度为i的节点在以前出现过,就只要判断这个串的长度%4==0,并且长度为len/2的节点在以前出现过,这样就很好的解决了这个问题;

主要是利用了fail链与fail树的性质,求出双倍回文!!

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<map>
 7 #include"set"
 8 #include"queue"
 9 #include"vector"
10 #include"iomanip"
11 #include"cstring"
12 #define inf 1<<29
13 #define ll long long
14 #define re register
15 #define il inline
16 #define rep(i,a,b) for(register int i=a;i<=b;++i)
17 #define file(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
18 using namespace std;
19 const int N=26,MAXN=500010;
20 struct Edge{
21     int to,net;
22 }e[MAXN];
23 int ans;
24 int head[MAXN],num_e;
25 il void link(int x,int y) {
26     e[++num_e].to=y,e[num_e].net=head[x],head[x]=num_e;
27 }
28 struct Palindromic_Tree{
29     int nxt[MAXN][N],fail[MAXN],len[MAXN],lst,n,p;
30     int S[MAXN];
31     il int newnode(int l) {
32         for(re int i=0;i<N;++i)
33             nxt[p][i]=0;
34         len[p]=l;
35         return p++;
36     }
37     il void init() {
38         p=0;
39         newnode(0);
40         newnode(-1);
41         n=0;lst=0;S[0]=-1;
42         fail[0]=1;
43     }
44     il int get_fail(int x){
45         while(S[n-len[x]-1]!=S[n]) x=fail[x];
46         return x;
47     }
48     il void add(int c) {
49         c-='a';
50         S[++n]=c;
51         int cur=get_fail(lst);
52         if(!nxt[cur][c]) {
53             int now=newnode(len[cur]+2);
54             fail[now]=nxt[get_fail(fail[cur])][c];
55             nxt[cur][c]=now;
56             link(fail[now],now);
57         }
58         lst=nxt[cur][c];
59     }
60     int T[MAXN];
61     il void dfs(int x) {
62         if(len[x]%4==0&&T[len[x]/2]) ans=max(ans,len[x]);
63         T[len[x]]++;
64         for(int i=head[x];i;i=e[i].net)
65             dfs(e[i].to);
66         T[len[x]]--;
67     }
68 }Pam;
69 char ch[MAXN];
70 inline int gi() {
71     re int res=0,f=1;re char ch=getchar();
72     while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
73     if(ch=='-') f=-1,ch=getchar();
74     while(ch>='0'&&ch<='9') res=res*10+ch-'0',ch=getchar();
75     return res*f;
76 }
77 int main(){
78     file("Y");
79     int n=gi();
80     scanf("%s",ch);int len=strlen(ch);
81     Pam.init();
82     for(re int i=0;i<len;++i) Pam.add(ch[i]);
83     Pam.dfs(0);
84     cout<<ans;
85     return 0;
86 }

 

posted @ 2017-07-12 20:54  Yinpz_23  阅读(175)  评论(0编辑  收藏  举报