http://hihocoder.com/problemset/problem/1457ios
val[i] 表示狀態i所表示的全部字符串的十進制之和spa
ans= ∑ val[i]
在後綴自動機上,從起始狀態走任意一條路徑到達任意一個狀態,這條路徑上的字符就是到達的狀態的字符串之一code
因此利用拓撲排序,記錄從起始狀態 走到這個狀態的 路徑數,即這個狀態的字符串個數 sumblog
若後綴自動機上有邊u-->v,加的是數字m,sum[v]+=sum[u],val[v]+=val[u]*10+sum[u]*m排序
至於多個串,中間加特殊字符,拓撲排序的時候不走特殊字符邊便可內存
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int mod=1e9+7; #define N 2000001 int tot=1,ch[N<<2][11]; int fa[N<<1],len[N<<1]; int dep[N<<1]; int last=1,p,q,np,nq; char s[N]; int v[N<<1]; int sa[N<<1]; int sum[N<<1],val[N<<1]; void extend(int c) { len[np=++tot]=len[last]+1; dep[np]=dep[last]+1; for(p=last;p && !ch[p][c];p=fa[p]) ch[p][c]=np; if(!p) fa[np]=1; else { q=ch[p][c]; if(len[q]==len[p]+1) fa[np]=q; else { nq=++tot; fa[nq]=fa[q]; memcpy(ch[nq],ch[q],sizeof(ch[nq])); fa[q]=fa[np]=nq; len[nq]=len[p]+1; dep[nq]=dep[p]+1; for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq; } } last=np; } void ADD(int &x,int y) { x+=y; x-=x>=mod ? mod : 0; } int main() { int n; scanf("%d",&n); int L; while(n--) { scanf("%s",s+1); L=strlen(s+1); for(int i=1;i<=L;++i) extend(s[i]-'0'); if(n) extend(10); } for(int i=1;i<=tot;++i) v[dep[i]]++; for(int i=1;i<=tot;++i) v[i]+=v[i-1]; for(int i=1;i<=tot;++i) sa[v[dep[i]]--]=i; sum[1]=1; int x; for(int i=1;i<tot;++i) { x=sa[i]; for(int j=0;j<10;++j) if(ch[x][j]) { ADD(sum[ch[x][j]],sum[x]); ADD(val[ch[x][j]],(1LL*val[x]*10+1LL*j*sum[x])%mod); } } int ans=0; for(int i=1;i<=tot;++i) ADD(ans,val[i]); printf("%d",ans); }
小Hi平時的一大興趣愛好就是演奏鋼琴。咱們知道一段音樂旋律能夠被表示爲一段數構成的數列。字符串
神奇的是小Hi發現了一部名字叫《十進制進行曲大全》的做品集,顧名思義,這部做品集裏有許多做品,可是全部的做品有一個共同特徵:只用了十個音符,全部的音符都表示成0-9的數字。get
如今小Hi想知道這部做品中全部不一樣的旋律的「和」(也就是把串當作數字,在十進制下的求和,容許有前導0)。答案有可能很大,咱們須要對(10^9 + 7)取摸。string
解題方法提示it
第一行,一個整數N,表示有N部做品。
接下來N行,每行包含一個由數字0-9構成的字符串S。
全部字符串長度和不超過 1000000。
共一行,一個整數,表示答案 mod (10^9 + 7)。
2 101 09
131