hdu5157 Harry and magic string 回文树
统计一个字符串中不相交的回文串的对数。
枚举以i为右端点的回文串,乘以在区间[i+1,n]的回文串个数,累加即可。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<map> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn=200100; const int INF=1e9+10; char s[maxn],t[maxn]; int ls,lt; struct PalinTree { int ch[maxn][26],f[maxn]; int n,tot,last; int len[maxn]; int s[maxn]; ll num[maxn]; ll cnt[maxn]; ll cnt2[maxn]; int newnode(int l) { MS0(ch[tot]); len[tot]=l; return tot++; } void init() { tot=0; newnode(0); newnode(-1); n=last=0; s[n]=-1;f[0]=1; num[0]=0;num[1]=-1; cnt[0]=0; cnt2[0]=0; } int get_fail(int x) { while(s[n-len[x]-1]!=s[n]) x=f[x]; return x; } void add(int c) { c-='a'; s[++n]=c; last=get_fail(last); if(!ch[last][c]){ int cur=newnode(len[last]+2); f[cur]=ch[get_fail(f[last])][c]; num[cur]=num[f[cur]]+1; ch[last][c]=cur; } last=ch[last][c]; cnt[n]=cnt[n-1]+num[last]; cnt2[n]=num[last]; } void build(char *str) { init(); int ls=strlen(str); REP(i,0,ls-1) add(str[i]); } };PalinTree ps,pt; int main() { freopen("in.txt","r",stdin); while(~scanf("%s",s)){ ls=lt=strlen(s); REP(i,0,ls-1) t[i]=s[ls-i-1]; ps.build(s); pt.build(t); ll ans=0; REP(i,1,ls-1){ ans+=1LL*ps.cnt[i]*pt.cnt2[ls-i]; } printf("%I64d\n",ans); } return 0; }
没有AC不了的题,只有不努力的ACMER!