\(\text{Solution}\)
一道回文树的模板题,只需一直跳\(fail\)指针,直到\(len_{fail[x]}\)为串\(x\)的一半。但这要显然会时超,考虑一个优化,因为对于回文树上的节点本身即是拓扑序,只需反向枚举就不会再重复枚举。
\(\text{Code}\)
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 5e5 + 5;
int len[N],tot,pre,fail[N],sz,ch[N][27],n;
char s[N],s1[N];
int add_nd(int x) {len[++sz] = x; return sz;}
int getl(int x){for (; s[tot] != s[tot - len[x] - 1]; x = fail[x]); return x;}
void insert(char c)
{
s[++tot] = c; int res = getl(pre);
if (!ch[res][c - 'a'])
{
int x = add_nd(len[res] + 2);
fail[x] = ch[getl(fail[res])][c - 'a'];
ch[res][c - 'a'] = x;
}
pre = ch[res][c - 'a'];
}
int main()
{
scanf("%d",&n);
scanf("%s",s1 + 1);
s[0] = '$',sz = -1,add_nd(0),add_nd(-1),fail[0] = 1;
for (int i = 1; i <= n; i++) insert(s1[i]);
int ans = 0;
for (int i = sz; i >= 2; i--)
if (len[i] % 4 == 0 && len[i] > ans)
{
int x = fail[i],flag = 0;
for (; len[x] * 2 >= len[i]; x = fail[x])
if (len[x] * 2 == len[i]) flag = 1;
if (flag) ans = max(ans,len[i]);
}
printf("%d\n",ans);
}