新学了一种神奇的数据结构叫回文树,然后就神奇的不用学马拉车了哈哈哈哈(之前还老被嘲讽不会马拉车QWQ)
非常nice的一点是,学完回文树之后发现它和AC自动机的原理几乎是一模一样的!所以只要会懂了AC自动机的原理回文树分分钟学会的事啊QWQ
回文树里的fail边代表某个回文子串的最长回文后缀子串节点是什么,然后ch[]就是在回文串的两端都加上同一个字母会转移到哪个节点。。。
本质相同的回文串就是回文树里的一个节点,所以就可以很方便的处理出现次数和长度等最大值或者计数问题了hhhh
(建议看一下某年讲这个的集训队论文)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=310005;
int len[maxn],sum[maxn],ch[maxn][26];
int n,c,cnt,now,fl[maxn],p;
char s[maxn];
ll ans=0;
int main(){
scanf("%s",s+1),n=strlen(s+1),s[0]='?';
len[1]=-1,fl[0]=1,now=cnt=1;
for(int i=1;i<=n;now=ch[now][c],sum[now]++,i++){
c=s[i]-'a';
for(;s[i-len[now]-1]!=s[i];now=fl[now]);
if(!ch[now][c]){
ch[now][c]=++cnt;
len[cnt]=len[now]+2;
if(len[cnt]==1) continue;
p=fl[now];
for(;s[i-len[p]-1]!=s[i];p=fl[p]);
fl[cnt]=ch[p][c];
}
}
for(int i=cnt;i>=2;i--){
sum[fl[i]]+=sum[i];
ans=max(ans,len[i]*(ll)sum[i]);
}
printf("%lld
",ans);
return 0;
}