标签:char algorithm using hid 它的 zoj ide int style
【算法】回文树
【题解】建回文数,然后一个回文子串出现的次数就是结点被访问的次数以及能包含它的结点被访问的次数。
根据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; }
标签:char algorithm using hid 它的 zoj ide int style
原文地址:http://www.cnblogs.com/onioncyc/p/6950869.html