1. 程式人生 > >HDU - 5157 :Harry and magic string (回文樹)

HDU - 5157 :Harry and magic string (回文樹)

last bit ++ name 每次 truct urn lld const

Sample Input

aca
aaaa
Sample Output
3
15
 

題意: 多組輸入,每次給定字符串S(|S|<1e5),求多少對不相交的回文串。

思路:可以用回文樹求出以每個位置結尾的回文串數,那麽累加得到前綴和; 倒著再做一遍得到每個位置為開頭的回文串數,乘正向求出的前綴和即可。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep2(i,a,b) for(int i=a;i>=b;i--)
using
namespace std; const int maxn=100010; struct PAT { struct node{ int len,num,fail,son[26]; }t[maxn]; int last,n,tot,s[maxn]; void init() { memset(t,0,sizeof(t)); tot=last=1; n=0; t[0].len=0; t[1].len=-1; t[0].fail=t[1].fail=1; s[
0]=-1; } int add(int c){ int p=last; s[++n]=c; while(s[n]!=s[n-1-t[p].len]) p=t[p].fail; if(!t[p].son[c]){ int v=++tot,k=t[p].fail; while(s[n]!=s[n-t[k].len-1]) k=t[k].fail; t[v].fail=t[k].son[c]; t[v].len=t[p].len+2
; t[v].num=t[t[v].fail].num+1; t[p].son[c]=v; } last=t[p].son[c]; return t[last].num; } }T; ll ans,sum[maxn];char c[maxn]; int main() { while(~scanf("%s",c+1)){ int N=strlen(c+1); T.init(); ans=0; rep(i,1,N) sum[i]=sum[i-1]+T.add(c[i]-a); T.init(); rep2(i,N,1) ans+=sum[i-1]*T.add(c[i]-a); printf("%lld\n",ans); } return 0; }

HDU - 5157 :Harry and magic string (回文樹)