hihoCoder1457 字尾自動機四·重複旋律7
阿新 • • 發佈:2020-07-20
字尾自動機
在後綴自動機上拓撲,計算每個節點的答案即可
然而我涼了很久……
原因:建圖陣列開小了!
注意:字尾自動機節點數開\(2n\),邊的條數開\(3n\)
C++ Code:
#include<bits/stdc++.h> #define N 3000005 #define mod 1000000007 #define int long long using namespace std; int n,T,cnt=1,last=1,t[N][11],pre[N],sz[N],len[N],rd[N]; int tot,head[N],nxt[N],d[N],d2[N],p[N],g[N]; char s[N]; char s1[1]; long long z[N],ans; queue<int>q; void ins(char *s) { n=strlen(s); for (int i=0;i<n;i++) { int c=(int)(s[i]-'0'); int p,q,np=++cnt; len[np]=len[last]+1; for (p=last;p&&!t[p][c];p=pre[p]) t[p][c]=np; if (!p) pre[np]=1; else { q=t[p][c]; if (len[p]+1==len[q]) pre[np]=q; else { cnt++; len[cnt]=len[p]+1; for (int j=0;j<11;j++) t[cnt][j]=t[q][j]; pre[cnt]=pre[q]; for (;p&&t[p][c]==q;p=pre[p]) t[p][c]=cnt; pre[q]=pre[np]=cnt; } } last=np; } } void add(int x,int y,int w) { tot++; d[tot]=y; d2[tot]=w; nxt[tot]=head[x]; head[x]=tot; rd[y]++; } main() { scanf("%lld",&T); z[1]=0; s1[0]=':'; for (int i=1;i<=T;i++) { scanf("%s",s); ins(s); if (i^T) ins(s1); } for (int i=1;i<=cnt;i++) head[i]=0,rd[i]=0; for (int i=1;i<=cnt;i++) for (int j=0;j<10;j++) if (t[i][j]) add(i,t[i][j],j); sz[1]=1; for (int i=1;i<=cnt;i++) if (!rd[i]) q.push(i); while (!q.empty()) { int u=q.front(); q.pop(); for (int i=head[u];i;i=nxt[i]) { int v=d[i]; long long cost=d2[i]; rd[v]--; z[v]+=z[u]*10+cost*sz[u],z[v]%=mod,sz[v]+=sz[u]; if (!rd[v]) { ans+=z[v]; ans%=mod; q.push(v); } } } cout << ans << endl; return 0; }