zoukankan      html  css  js  c++  java
  • P2679 子串

    P2679 子串

    题目描述 有两个仅包含小写英文字母的字符串 A 和 B。

    现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一个新的字符串。请问有多少种方案可以使得这个新串与字符串 B 相等?

    注意:子串取出的位置不同也认为是不同的方案。

    答案模1000000007

    Solution

    (dp_{i, j, k, 1/0}) 表示 考虑 (A)(i) 个, (B)(j) 个, 在 (A) 中选取 (k) 个子串, 第 (i) 位 选 / 不选进子串 的方案数 转移时, 考虑前一种状态, 判断新加入的字符作为新子串还是老子串即可 $$dp_{i, j, k, 0} = dp_{i - 1, j, k, 0} + dp_{i - 1, j, k, 1}$$$$dp_{i, j, k, 1} = dp_{i - 1, j - 1, k - 1, 0} + dp_{i - 1, j - 1, k - 1, 1} + dp_{i - 1, j - 1, k, 1} [if(A_ == B_)]$$$$dp_{i, j, k, 0} = 0 [Else]$$ 不选直接继承上一步答案即可 选的话为以下三种情况的和: 前两项是作为新子串, 第三项是作为后缀接在老的子串后面的方案数

    但是这样转移的话空间无法承受, 观察转移只与 (i - 1) 有关, 滚掉 (i) 维即可

    Code

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #include<climits>
    #define LL long long
    #define REP(i, x, y) for(int i = (x);i <= (y);i++)
    using namespace std;
    int RD(){
        int out = 0,flag = 1;char c = getchar();
        while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
        while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
        return flag * out;
        }
    const int maxn = 2019, M = 1000000007;
    int lenA, lenB, K;
    char A[maxn], B[maxn];
    int dp[2][419][419][2];//匹配到B的前i个,A中选k段,当前i选或不选的方案数
    int main(){
    	lenA = RD(), lenB = RD(), K = RD();
    	scanf("%s%s", A + 1, B + 1);
    	dp[0][0][0][0] = dp[1][0][0][0] = 1;//滚动刚开始为1,对应起点为0
    	REP(i, 1, lenA){
    		int now = i & 1, pre = now ^ 1;
    		REP(j, 1, lenB){
    			REP(k, 1, K){
    				dp[now][j][k][0] = ((dp[pre][j][k][0] + dp[pre][j][k][1]) % M + M) % M;//不选
    				if(A[i] == B[j]){
    					dp[now][j][k][1] = //选
    					((dp[pre][j - 1][k - 1][0] + 
    					dp[pre][j - 1][k - 1][1]) % M + M) % M + //前面这两种情况都可以开新子串
    					dp[pre][j - 1][k][1];//或者接在之前的串后面
    					dp[now][j][k][1] = (dp[now][j][k][1] % M + M) % M;
    					}
    				else dp[now][j][k][1] = 0;
    				}
    			}
    		}
    	printf("%d
    ", ((dp[lenA & 1][lenB][K][0] + dp[lenA & 1][lenB][K][1]) % M + M) % M);
    	return 0;
    	}
    
  • 相关阅读:
    2-5 Flutter开发环境与Android开发环境设置详解(Windows)
    2-3 Flutter开发环境与iOS开发环境设置(Mac)
    2-1 本章作业&2-2 开发系统与工具选择
    ASP.NET Core会议管理平台实战_4、参数校验、操作结果封装,注册参数配置
    ASP.NET Core会议管理平台实战_3、认证、授权表迁移
    29.镜像容器与仓库
    27.集成EFCore配置Client和API
    26.OpenIdConnect获取用户信息的两种方式
    25.ProfileService实现(调试)
    24.集成ASP.NETCore Identity
  • 原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9875838.html
Copyright © 2011-2022 走看看