• P2679 子串 DP


    P2679 子串 DP

    从字符串A中取出(k)段子串,按原顺序拼接,问存在多少个方案使拼接的字符串与字符串B相同

    淦,又是这种字符串dp

    设状态(ans[i][j][k])表示A串位置(i),B串位置(j),已取出(k)段字符串,不管当前位置(i)是否能匹配上的方案数,(g[i][j][k])表示A串位置(i),B串位置(j),已取出(k)段字符串,当前A串位置(i)已匹配上B串位置(j)(即(a[i]==b[j]))的方案数。

    状态转移:

    if(a[i]==b[j]) // 如果匹配上了
        g[i][j][p]=(g[i-1][j-1][p]+ans[i-1][j-1][p-1])%MOD;
    	// g[i-1][j-1][p] 表示与上一个匹配连在一起
    	// ans[i-1][j-1][p-1] 以前的方案数
    else g[i][j][p]=0;
    
    ans[i][j][p]=(g[i][j][p]+ans[i-1][j][p])%MOD;	
    // g[i][j][p] 现在新匹配上的
    // ans[i-1][j][p] 以前的方案数
    

    然后为了优化空间就上了滚动数组,见代码:

    #include <cstdio>
    #define MAXN 1010
    #define MOD 1000000007
    using namespace std;
    int n,m,k;
    int ans[3][MAXN][MAXN],g[3][MAXN][MAXN];
    char a[MAXN],b[MAXN];
    int main(){
    	scanf("%d %d %d", &n, &m, &k);
    	scanf("%s%s", a+1, b+1);
    	int cur=1;
    	ans[0][0][0]=1;
    	for(int i=1;i<=n;++i){
    		ans[cur][0][0]=1;
    		for(register int j=1;j<=m;++j)
    			for(register int p=1;p<=k;++p){
    				if(a[i]==b[j]) g[cur][j][p]=(g[cur^1][j-1][p]+ans[cur^1][j-1][p-1])%MOD;
    				else g[cur][j][p]=0;
    				ans[cur][j][p]=(g[cur][j][p]+ans[cur^1][j][p])%MOD;
    			}
    		cur^=1;
    	}
    	printf("%d
    ", ans[cur^1][m][k]);
    	return 0;
    }
    
  • 相关阅读:
    vue 兼容IE报错解决方案
    JDK1.8 ArrayList 源码解析
    Mac nasm 汇编入门
    命令模式
    模板方法
    Mysql Limit 调优
    观察者模式
    外观模式
    Rest- Client
    MongoDB数据库 5分钟快速上手
  • 原文地址:https://www.cnblogs.com/santiego/p/11437162.html
Copyright © 2020-2023  润新知