zoukankan      html  css  js  c++  java
  • 【后缀自动机】【拓扑排序】【动态规划】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]='';
    	}
    	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
    ",ans);
    	return 0;
    }
  • 相关阅读:
    【bzoj1707/Usaco2007 Nov】tanning分配防晒霜——贪心+优先队列
    【bzoj1754/Usaco2005 qua】Bull Math——高精度乘法
    【bzoj1709/Usaco2007 Oct】Super Paintball超级弹珠——递推
    【bzoj2060/Usaco2010 Nov】Visiting Cows 拜访奶牛——树形dp
    【bzoj1710/Usaco2007 Open】Cheappal 廉价回文——区间dp
    【bzoj1828/Usaco2010 Mar】balloc 农场分配——贪心+差分+优先队列
    【bzoj4552/Tjoi2016&Heoi2016】排序——二分+线段树/平衡树+线段树分裂与合并
    【bzoj2083/Poi2010】Intelligence test——二分+贪心
    【bzoj1596/Usaco2008 Jan】电话网络——dfs
    【bzoj1782/Usaco2010 Feb】slowdown 慢慢游——dfs序+树状数组
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/6637708.html
Copyright © 2011-2022 走看看