【后缀自动机】【拓扑排序】【动态规划】hihocoder1457 后缀自动机四·重复旋律7

 

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
#define MOD 1000000007ll
#define MAXL 2000000
#define MAXC 11
char s[MAXL+10];
int len/*文本串长度*/;
struct SAM{
	int n/*状态数0~n-1*/,maxlen[2*MAXL+10],minlen[2*MAXL+10],trans[2*MAXL+10][MAXC],slink[2*MAXL+10];
	int new_state(int _maxlen,int _minlen,int _trans[],int _slink){
		maxlen[n]=_maxlen;
		minlen[n]=_minlen;
		for(int i=0;i<MAXC;++i){
			if(_trans==NULL){
				trans[n][i]=-1;
			}
			else{
				trans[n][i]=_trans[i];
			}
		}
		slink[n]=_slink;
		return n++;
	}
	int add_char(char ch,int u){
		if(u==-1){
			return new_state(0,0,NULL,-1);
		}
		int c=ch-'0';
		int z=new_state(maxlen[u]+1,-1,NULL,-1);
		int v=u;
		while(v!=-1 && trans[v][c]==-1){
			trans[v][c]=z;
			v=slink[v];
		}
		if(v==-1){//最简单的情况,suffix-path(u->S)上都没有对应字符ch的转移
			minlen[z]=1;
			slink[z]=0;
			return z;
		}
		int x=trans[v][c];
		if(maxlen[v]+1==maxlen[x]){//较简单的情况,不用拆分x
			minlen[z]=maxlen[x]+1;
			slink[z]=x;
			return z;
		}
		int y=new_state(maxlen[v]+1,-1,trans[x],slink[x]);//最复杂的情况,拆分x
		slink[y]=slink[x];
		minlen[x]=maxlen[y]+1;
		slink[x]=y;
		minlen[z]=maxlen[y]+1;
		slink[z]=y;
		int w=v;
		while(w!=-1 && trans[w][c]==x){
			trans[w][c]=y;
			w=slink[w];
		}
		minlen[y]=maxlen[slink[y]]+1;
		return z;
	}
}sam;
int m;
queue<int>q;
int ru[MAXL*2+10];
ll paths[MAXL*2+10],f[MAXL*2+10],ans;
int main(){
//	freopen("hihocoder1457.in","r",stdin);
	scanf("%d",&m);
	for(int i=1;i<=m;++i){
		scanf("%s",s+len);
		len=strlen(s);
		s[len]=':';
		s[++len]='\0';
	}
	int U=sam.add_char(0,-1);
	for(int i=0;i<len;++i){
		U=sam.add_char(s[i],U);
	}
	for(int i=0;i<sam.n;++i){
		for(int j=0;j<MAXC;++j){
			if(sam.trans[i][j]!=-1){
				++ru[sam.trans[i][j]];
			}
		}
	}
	paths[0]=1;
	for(int i=0;i<sam.n;++i){
		if(!ru[i]){
			q.push(i);
		}
	}
	while(!q.empty()){
		U=q.front(); q.pop();
		for(int i=0;i<MAXC;++i){
			if(i!=':'-'0'){
				paths[sam.trans[U][i]]+=paths[U];
				f[sam.trans[U][i]]=(f[sam.trans[U][i]]+(f[U]*10ll%MOD+(ll)i*(paths[U]%MOD)%MOD)%MOD)%MOD;
			}
			--ru[sam.trans[U][i]];
			if(!ru[sam.trans[U][i]]){
				q.push(sam.trans[U][i]);
			}
		}
	}
	for(int i=0;i<sam.n;++i){
		ans=(ans+f[i])%MOD;
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2017-03-29 00:04  AutSky_JadeK  阅读(273)  评论(0编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト