转自:https://www.cnblogs.com/lidaxin/p/5289228.html
https://blog.csdn.net/weixin_34416754/article/details/93613251
题意:给出几个字符串,计算出他们所有不重复不计前缀0的子串和,取余2011
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int mod=2012,maxn=400010;
char ss[maxn],s[maxn];
int tt[maxn],last,cur=1,cnt=1,n,len,sum[maxn],ch[maxn][10],fa[maxn],dis[maxn];
int c[maxn],q[maxn];
void add(int c,int id){
last=cur;cur=++cnt;
int p=last;dis[cur]=id;
for(;p&&!ch[p][c];p=fa[p])ch[p][c]=cur;
if(!p)fa[cur]=1;
else{
int q=ch[p][c];
if(dis[q]==dis[p]+1)fa[cur]=q;
else{
int nt=++cnt;dis[nt]=dis[p]+1;
memcpy(ch[nt],ch[q],sizeof(ch[0]));
fa[nt]=fa[q];fa[q]=fa[cur]=nt;
for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nt;
}
}
}
void rsort(){
memset(c,0,sizeof(c));
for(int i=1;i<=cnt;++i)c[dis[i]]++;
for(int i=1;i<=cnt;++i)c[i]+=c[i-1];
for(int i=1;i<=cnt;++i)q[c[dis[i]]--]=i;
}
int main(){
while(cin>>n){
cnt=1;memset(fa,0,sizeof(fa));
memset(ch,0,sizeof(ch));
for(int i=1;i<=n;++i){
scanf("%s",ss+1);
cur=1;len=strlen(ss+1);
for(int j=1;j<=len;++j)add(ss[j]-'0',j);
}
rsort();//先排一遍序保证计算顺序没有问题,保证一个点在更新别的点之前已经被所有能到它的点更新过;
memset(sum,0,sizeof(sum));memset(tt,0,sizeof(tt));
sum[1]=0;tt[1]=1;
for(int i=1,j;i<=cnt;++i){
j=q[i];
for(int k=0,t;k<10;++k){
if(j==1&&(!k))continue;
t=ch[j][k];
(sum[t]+=tt[j]*k+sum[j]*10)%=mod;
(tt[t]+=tt[j])%=mod;
//cout<<sum[t]<<' '<<tt[t]<<endl;
}
}
int ans=0;
for(int i=1;i<=cnt;++i){(ans+=sum[i])%=mod;}
printf("%d\n",ans);
}
//system("pause");
return 0;
}