zoukankan      html  css  js  c++  java
  • BZOJ 3530 [Sdoi2014]数数

    题解:建立AC自动机,然后Dp

    考虑长度与n相等时

    f[i][j][2]表示第i位匹配到AC自动机第j号节点,是否顶着上界的方案数

    转移枚举这一位填什么

    注意,如果当前节点沿Fail树能走到单词节点就不能转移到他

    长度<lenn不用考虑顶上界

    问题:不明白最后统计答案的方式

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int maxn=2009;
    const int mm=1000000007;
    
    int n,m;
    char s[maxn];
    int a[maxn];
    
    int nn;
    int ch[maxn][10];
    int val[maxn];
    void Ins() {
    	int n=strlen(s);
    	int u=0;
    	for(int i=0; i<n; ++i) {
    		int c=s[i]-'0';
    		if(!ch[u][c])ch[u][c]=++nn;
    		u=ch[u][c];
    	}
    	val[u]=1;
    }
    
    queue<int>q;
    int fai[maxn];
    void Getfail(){
    	for(int c=0;c<=9;++c){
    		int v=ch[0][c];
    		if(v)q.push(v);
    	}
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		for(int c=0;c<=9;++c){
    			int v=ch[u][c];
    			if(!v)continue;
    			q.push(v);
    			val[v]|=val[u];
    			int j=fai[u];
    			while((j)&&(!ch[j][c]))j=fai[j];
    			fai[v]=ch[j][c];
    			val[v]|=val[fai[v]];
    		}
    	}
    }
    
    long long f[maxn][maxn][2];
    long long ans;
    
    int main() {
    	scanf("%s",s);
    	n=strlen(s);
    	for(int i=1; i<=n; ++i)a[i]=s[i-1]-'0';
    	scanf("%d",&m);
    	while(m--) {
    		scanf("%s",s);
    		Ins();
    	}
    	Getfail();
    	
    	memset(f,0,sizeof(f));
    	for(int c=1;c<=9;++c){
    		int v=ch[0][c];
    		if(val[v])continue;
    		if(c<a[1])f[1][v][0]++;
    		if(c==a[1])f[1][v][1]++;
    	}
    	for(int i=1;i<n;++i){
    		for(int j=0;j<=nn;++j){
    			for(int c=0;c<=9;++c){
    				int u=j;
    				while((u)&&(!ch[u][c]))u=fai[u];
    				int v=ch[u][c];
    				if(val[v])continue;
    				if(c<a[i+1]){
    					f[i+1][v][0]=(f[i+1][v][0]+f[i][j][0]+f[i][j][1])%mm;
    				}
    				if(c==a[i+1]){
    					f[i+1][v][0]=(f[i+1][v][0]+f[i][j][0])%mm;
    					f[i+1][v][1]=(f[i+1][v][1]+f[i][j][1])%mm;
    				}
    				if(c>a[i+1]){
    					f[i+1][v][0]=(f[i+1][v][0]+f[i][j][0])%mm;
    				}
    			}
    		}
    	}
    	for(int j=0;j<=nn;++j){
    		ans=(ans+f[n][j][0]+f[n][j][1])%mm;
    	}
    //	ans=(f[n][0][0]+f[n][0][1])%mm;
    //	for(int c=0;c<=9;++c){
    //		int v=ch[0][c];
    //		if(v){
    //			ans=(ans+f[n][v][0]+f[n][v][1])%mm;
    //		}
    //	}
    //	cout<<ans<<endl;
    	--n;
    	memset(f,0,sizeof(f));
    	for(int c=1;c<=9;++c){
    		int v=ch[0][c];
    		if(val[v])continue;
    		f[1][v][0]++;
    	}
    	for(int i=1;i<n;++i){
    		for(int j=0;j<=nn;++j){
    			for(int c=0;c<=9;++c){
    				int u=j;
    				while((u)&&(!ch[u][c]))u=fai[u];
    				int v=ch[u][c];
    				if(val[v])continue;
    				f[i+1][v][0]=(f[i+1][v][0]+f[i][j][0])%mm;
    			}
    		}
    //		ans=(ans+f[i+1][0][0])%mm;
    //		for(int c=0;c<=9;++c){
    //			int v=ch[0][c];
    //			if(!v)continue;
    //			ans=(ans+f[i+1][v][0])%mm;
    //		}
    	}
    	for(int i=1;i<=n;++i){
    		for(int j=0;j<=nn;++j){
    			ans=(ans+f[i][j][0])%mm;
    		}
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    windows系统设置虚拟机开机自启并运行虚拟系统
    Pycharm模板添加默认信息
    (翻译)从底层了解ASP.NET体系结构 [转]
    sql2000安装在win2003后只有在本机才能访问,局域网内其他机器不能访问
    Web上传文件的原理及实现[转]
    Http 请求处理流程[转]
    .net 必知
    sql2000数据库在企业管理器中显示置疑(suspect),在查询分析器不显示。在企业管理器中附加:提示错误823
    HTTP请求过程简介[转]
    面向对象
  • 原文地址:https://www.cnblogs.com/zzyer/p/8455510.html
Copyright © 2011-2022 走看看