回文自动机模板

 1 #include <bits/stdc++.h>
 2 
 3 const int N = 500010;
 4 
 5 struct Edge {
 6     int nex, v;
 7 }edge[N]; int tp;
 8 
 9 int tr[N][26], fail[N], len[N], tot = 1, last = 1, e[N], Ans, stk[N], top, n;
10 char str[N];
11 
12 inline void add(int x, int y) {
13     edge[++tp].v = y;
14     edge[tp].nex = e[x];
15     e[x] = tp;
16 }
17 
18 inline void init() {
19     len[1] = -1;
20     fail[0] = fail[1] = 1;
21     return;
22 }
23 
24 inline int getpos(int x, int i) {
25     while(str[i] != str[i - len[x] - 1]) {
26         x = fail[x];
27     }
28     return x;
29 }
30 
31 inline void insert(int i, int f) {
32     int x = getpos(last, i);
33     if(!tr[x][f]) {
34         ++tot;
35         fail[tot] = tr[getpos(fail[x], i)][f];
36         len[tot] = len[x] + 2;
37         tr[x][f] = tot;
38     }
39     last = tr[x][f];
40     return;
41 }
42 
43 inline void Insert() {
44     for(int i = 1; i <= n; i++) {
45         insert(i, str[i] - 'a');
46     }
47     return;
48 }
49 
50 void DFS(int x, int p) {
51     if(len[x - 1] >= 2 && (!(len[x - 1] & 1))) {
52         stk[++top] = len[x - 1];
53         while(stk[p] * 2 < stk[top]) {
54             ++p;
55         }
56         if(stk[p] * 2 == stk[top]) {
57             Ans = std::max(stk[top], Ans);
58         }
59     }
60     for(int i = e[x]; i; i = edge[i].nex) {
61         int y = edge[i].v;
62         DFS(y, p);
63     }
64     if(len[x - 1] >= 2 && (!(len[x - 1] & 1))) {
65         top--;
66     }
67     return;
68 }
69 
70 int main() {
71 
72     scanf("%d%s", &n, str + 1);
73     init();
74     Insert();
75 
76     add(2, 1);
77     for(int i = 2; i <= tot; i++) {
78         add(fail[i] + 1, i + 1);
79     }
80 
81     DFS(2, 0);
82     printf("%d\n", Ans);
83     return 0;
84 }
AC代码

以SHOI2011 双倍回文为例。

转载于:https://www.cnblogs.com/huyufeifei/p/10999790.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值