迴文樹模板 2018 icpc南京站網路賽 I. Skr
阿新 • • 發佈:2018-12-18
引用:
#include "cstdio" #include "algorithm" #include "cstring" #define maxn 10000005 #define sigma 26 struct ptree{ char s[maxn]; int next[maxn][sigma],fail[maxn],cnt[maxn],len[maxn]; int last,n,p; long long res; inline int newnode(int l){ cnt[p]=0; len[p]=l; return p++; } inline void init(){ newnode(0),newnode(-1);//two roots s[n]=-1; fail[0]=1; } inline int FL(int x){ while(s[n-len[x]-1]!=s[n]) x=fail[x]; return x; } void add(char c){ c-='a'; s[++n]=c; int cur=FL(last); if(!next[cur][c]){ int now=newnode(len[cur]+2); fail[now]=next[FL(fail[cur])][c]; next[cur][c]=now; } last=next[cur][c]; ++cnt[last]; } inline unsigned long long count(){ unsigned long long pk=0; for(int i=p-1;~i;--i){ cnt[fail[i]]+=cnt[i]; pk+=((unsigned long long)cnt[i])*len[i]; } return pk; } } p; char s[maxn]; int i,j,k; int main(){ scanf("%s",s); j=strlen(s); p.init(); for(i=0;i<j;++i) p.add(s[i]); printf("%llu\n",p.count()); return 0; }
題意:給你一個數字串,求所有本質不同的迴文數字串的和%1e9+7
學會迴文樹後,這題就變成水題了,只需在每次插入的時候,如果插入的是一個新節點,那麼新節點num代表的數字可以由父親*10+num*10^(len-1)+num得到,然後加到答案即可,len表示這個節點代表的迴文數字串的長度。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int mod=1e9+7,maxn=2e6+10; ll ans=0,po[maxn]; struct pal { char s[maxn]; int next[maxn][10],fail[maxn],len[maxn]; int last,n,p; ll res[maxn]; int newnode(int l) { len[p]=l; return p++; } void init() { newnode(0),newnode(-1); s[n]=-1; fail[0]=1; } int FL(int x) { while(s[n-len[x]-1]!=s[n])x=fail[x]; return x; } void add(char c) { int num=c-'0'; c-='0'; s[++n]=c; int cur=FL(last); if(!next[cur][c]) { int now=newnode(len[cur]+2); fail[now]=next[FL(fail[cur])][c]; next[cur][c]=now; if(cur!=1) res[now]=(po[len[cur]+2]*c+c+res[cur]*10)%mod; else res[now]=c; ans=(ans+res[now])%mod; } last=next[cur][c]; } }P; char s[maxn]; int main() { scanf("%s",s); int len=strlen(s); po[1]=1; for(int i=2;i<=len;i++)po[i]=(po[i-1]*10)%mod; P.init(); for(int i=0;i<len;i++) P.add(s[i]); printf("%lld\n",ans); }