zoukankan      html  css  js  c++  java
  • [BZOJ 2061] Country(KMP+记忆化搜索)

    [BZOJ 2061] Country(KMP+记忆化搜索)

    题面

    gaoxin神犇频繁的在发言中表现对伟大,光荣,正确的xx的热爱,我们可以做如下定义: A=伟大,光荣,正确的 B=xx C=引领我们向前 赞美祖国=ABC 拼命赞美祖国=赞美祖国10 gaoxin的发言=拼命赞美祖国100 显然这个定义必须是无环的。 WJMZBMR感到十分的有压力, 他好不容易数出了某个字串的出现次数。。。

    某天他打开电视,发现某人的发言有同样的结构。。他很无语。。。想知道某些字串出现的次数。。 你能帮帮他吗?

    一些定义: 为了简化期间,在输入中用英文表示.

    字符串:由小写字母组成如a

    字串名:一定是大写字母如A 那么上面的系统可以写成 A=greatglorycorrect B=xx C=leadusgo D=ABC E=DDDDdjh F=EEEEEgoodbye 同时存在一个母字串名,他就是某人的发言

    分析

    记忆化搜索,(dp[i][j])表示当前处理到字符串(i)(还未与i匹配),上一次模板串匹配到(j)位时的匹配次数。

    我们遍历i中的每个字符,如果是小写字母,就利用KMP匹配,并记录现在已经匹配到的位置x.如果是大写字母id,就递归dfs(id,x)。为了更新匹配位置,我们要额外维护一个数组(pos[i][j])表示当前处理到字符串(i)(还未与i匹配),上一次模板串匹配到(j)位,匹配结束后模板串的位置。递归完成后把x赋值为(pos[id][x]). 同时更新(dp[i][j]). 遍历完每个字符后把(pos[i][j])赋值为x

    最终答案为(dp[s][0]) (这也是为什么我们定义j表示初始时的匹配位置,要不然我们不知道最后匹配到哪里)

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    #include<cctype>
    #include<queue>
    #define maxn 26
    #define maxl 100000
    #define mod 10000
    
    using namespace std;
    int n,s;
    
    
    inline bool isAlpha(char c){
    	return c>='A'&&c<='Z';
    }
    void get_nex(char *s,int n,int *nex) {
    	nex[1]=0;
    	for(int i=2,j=0; i<=n; i++) {
    		while(j&&s[j+1]!=s[i]) j=nex[j];
    		if(s[j+1]==s[i]) j++;
    		nex[i]=j;
    	}
    }
    
    int a[maxn+5][maxl+5];
    int len[maxn+5];
    char tp[maxn+5],lentp;
    int nex[maxl+5];
    
    int dp[maxn+5][maxl+5];
    //dp[i][j]表示字符串i,当前还未匹配时末尾已经与模板串匹配了j位,
    //串i里包含模板串的个数 
    int pos[maxn+5][maxl+5];//pos[i][j]表示匹配结束后KMP指针的位置 
    int dfs(int i,int j){
    	if(dp[i][j]!=-1) return dp[i][j];
    	dp[i][j]=0;
    	int x=j;
    	for(int k=1;k<=len[i];k++){
    		if(isAlpha(a[i][k])){
    			int id=a[i][k]-'A'+1;
    			dp[i][j]+=dfs(id,x);
    			dp[i][j]%=mod;
    			x=pos[id][x]; 
    		}else{
    			int p=x;
    			while(p&&tp[p+1]!=a[i][k]) p=nex[p];
    			if(tp[p+1]==a[i][k]) p++;
    			x=p;
    			if(x==lentp){
    				dp[i][j]++;
    				dp[i][j]%=mod;
    			} 
    		}
    	}
    	pos[i][j]=x;
    	return dp[i][j];
    }
    
    char in[maxl+5];
    int main() {
    	scanf("%d",&n);
    	scanf("%s",in+1);
    	s=in[1]-'A'+1;
    	for(int i=1; i<=n; i++) {
    		scanf("%s",in+1);
    		int l=strlen(in+1);
    		for(int j=3; j<=l; j++) a[in[1]-'A'+1][j-2]=in[j];
    		len[i]=l-2;
    	}
    	scanf("%s",tp+1);
    	lentp=strlen(tp+1); 
    	get_nex(tp,lentp,nex);
    	memset(dp,0xff,sizeof(dp));
    	dfs(s,0); 
    	printf("%d
    ",dp[s][0]);
    }
    
  • 相关阅读:
    Java的静态块与实例块(转)
    Programming Ability Test学习 1031. Hello World for U (20)
    Programming Ability Test学习 1011. World Cup Betting (20)
    Programming Ability Test学习 1027. Colors in Mars (20)
    Programming Ability Test学习 1064. Complete Binary Search Tree (30)
    Programming Ability Test学习 1008. Elevator (20)
    【maven详解-生命周期】Maven的生命周期和插件
    【maven详解-插件】maven插件学习之源码插件Source Xref
    $(document).ready(){}、$(fucntion(){})、(function(){})(jQuery)onload()的区别
    你还没真的努力过,就轻易输给了懒惰
  • 原文地址:https://www.cnblogs.com/birchtree/p/12172306.html
Copyright © 2011-2022 走看看