[APIO2014] 回文串
新学了一种神奇的数据结构叫回文树,然后就神奇的不用学马拉车了哈哈哈哈(之前还老被嘲讽不会马拉车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\n",ans); return 0; }
我爱学习,学习使我快乐