[hihocoder1457]
- 一个一个找显然会T飞
- 考虑增量法,如何利用上一次的信息
- sum(x)表示在DAG上以x结尾的所有串的答案,tot(x)表示在DAG上以x结尾的串有tot(x)个
- sum(to[x][c])=\sum sum(x)*10+tot(x)*c
- 按照Topsort计算即可
Code
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int mod=1e9+7;
const int N=2e6;
int tot[N],sum[N],du[N],pre[N],maxn[N],to[N][20],n,cnt,ans,last;
string s,a;
inline int read(){
int num=0;char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))num=num*10+ch-'0',ch=getchar();
return num;
}
inline void Print(int x){if(x>9)Print(x/10);putchar(x%10+'0');}
////////////////////////////////////////////////////////////////////
void insert(int c){
int x=++n,p=last,q; last=n,maxn[x]=maxn[p]+1;
while(p&&!to[p][c])to[p][c]=x,p=pre[p];
if(!p){pre[x]=1;return;}
if(maxn[q=to[p][c]]==maxn[p]+1)pre[x]=q;
else{
int y=++n; maxn[y]=maxn[p]+1;
memcpy(to[y],to[q],sizeof(to[q]));
pre[y]=pre[q],pre[q]=pre[x]=y;
while(to[p][c]==q)to[p][c]=y,p=pre[p];
}
}
queue<int> q;
int main()
{
cnt=read();
rep(i,1,cnt){cin>>a;s+=a;s+='@';}
n=last=1;
int len=s.size();
rep(i,0,len-1)insert(s[i]-'0');
rep(i,1,n){
rep(c,0,9){
if(to[i][c])du[to[i][c]]++;
}
}
rep(i,1,n)if(!du[i])q.push(i);
tot[1]=1;
while(q.size()){
int x=q.front();q.pop();
rep(c,0,9)if(to[x][c]){
int y=to[x][c];
tot[y]=(tot[x]+tot[y])%mod;
sum[y]=(sum[y]+1LL*sum[x]*10%mod+1LL*tot[x]*c%mod)%mod;
du[y]--;
if(!du[y])q.push(y);
}
}
rep(i,1,n)ans=(ans+sum[i])%mod;
Print(ans);
return 0;
}