![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
以SHOI2011 双倍回文为例。