[hihocoder1457] 后缀自动机+拓扑排序

[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;
}

 

    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/strangeDDDF/article/details/86748219
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞