BZOJ3676 [Apio2014]回文串
Posted ONION_CYC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ3676 [Apio2014]回文串相关的知识,希望对你有一定的参考价值。
【算法】回文树
【题解】建回文数,然后一个回文子串出现的次数就是结点被访问的次数以及能包含它的结点被访问的次数。
根据fail树反向建新树,那么答案就是结点所在子树的权值和(权值就是结点被访问次数)。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=300010; char s[maxn]; int n,len,l,sz,first[maxn],tot; long long ans; struct trees{int len,fail,t[30],num;}t[maxn]; struct edges{int v,from;}e[maxn*3]; void insert(int u,int v) {tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;} int getfail(int x) { while(s[len-t[x].len-1]!=s[len])x=t[x].fail; return x; } void tree_work() { int x=s[++len]-‘a‘; l=getfail(l); if(!t[l].t[x]) { sz++; t[sz].len=t[l].len+2; t[sz].num=1; t[sz].fail=t[getfail(t[l].fail)].t[x];//偏小 insert(t[sz].fail,sz); t[l].t[x]=sz; } else { t[t[l].t[x]].num++; } l=t[l].t[x]; } long long dfs(int x) { long long sum=t[x].num; for(int i=first[x];i;i=e[i].from) { sum+=dfs(e[i].v); } ans=max(ans,1ll*t[x].len*sum); return sum; } int main() { scanf("%s",s+1); n=strlen(s+1); sz=1; s[0]=-1;// t[0].len=0;t[1].len=-1; t[0].fail=t[1].fail=1; t[0].num=t[1].num=1; insert(1,0); len=l=ans=0; for(int i=1;i<=n;i++)tree_work(); dfs(1); printf("%lld",ans); return 0; }
以上是关于BZOJ3676 [Apio2014]回文串的主要内容,如果未能解决你的问题,请参考以下文章
[BZOJ3676][APIO2014]回文串(Manacher+SAM)