zoukankan      html  css  js  c++  java
  • [NOIp2015]子串

    (mathcal{color{red}{Description}})

    有两个仅包含小写英文字母的字符串 (A)(B)

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

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

    对于所有 (10) 组数据:(1≤n≤1000,1≤m≤200,1≤k≤m)

    (mathcal{color{red}{Solution}})

    单纯的我一开始以为是一道状压……然后看到数据范围后是崩溃的……

    仔细想了想,好像状压的确会枚举好多智障的冗余状态……那么就开始考虑正常向的(DP)……设(dp_{i,j,k})表示(A)中匹配到第(i)位,(B)中匹配到第(j)位,共用了(k)个子串的方案数。那么状态转移方程很显然就是(dp_{i,j,k} = (dp_{i-1,j-1,k} + dp_{i - 1, j - 1, k - 1}) imes [A_i = B_j])……

    但想了想,发现是不对的……因为事实上我们没有考虑上一位没有选这种情况……于是我就不会惹……于是选择看题解(OTZ)

    然后发现自己被秀了一脸(qwq)

    我们考虑用两个(DP)数组来记录状态,(f_{i,j,k})表示(A)中匹配到第(i)位,(B)中匹配到第(j)位,共用了(k)个子串,(A_i)这一位一定要用的的方案数。(dp_{i,j,k})表示(A)中匹配到第(i)位,(B)中匹配到第(j)位,共用了(k)个子串,(A_i)这一位可用可不用的方案数。

    那么转移方程就是$$f_{i,j,k} = (dp_{i-1,j-1,k-1} + f_{i-1,j-1,k}) imes [A_i = B_j]$$和$$dp_{i,j,k} = dp_{i-1,j,k}+f_{i,j,k}$$第一个方程是基于是否和上一位连成一串得来的,第二个方程是基于是否选(A_i)的得来的。

    滚啊滚啊~

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define MAXN 1010
    #define MAXM 210
    #define mod 1000000007
    
    using namespace std ;
    char A[MAXN], B[MAXM] ; int i, j, k, d ;
    int N, M, K, dp[2][MAXM][MAXM], f[2][MAXM][MAXM];
    
    int main(){
        cin >> N >> M >> K ; dp[0][0][0] = 1 ;
        for(i = 1; i <= N; i ++) cin >> A[i] ;
        for(i = 1; i <= M; i ++) cin >> B[i] ;
        for(d = i = 1; i <= N; i ++, d ^= 1){
            dp[d][0][0] = 1 ;
            for(j = 1; j <= M; j ++)
                for(k = 1; k <= K ;k ++){
                    if(A[i] == B[j]) f[d][j][k] = (dp[d ^ 1][j - 1][k - 1] + f[d ^ 1][j - 1][k]) % mod ;
                    else f[d][j][k] = 0 ;
                    dp[d][j][k] = (dp[d ^ 1][j][k] + f[d][j][k]) % mod ;
                }
        }
        cout << dp[N & 1][M][K]% mod ;
    }
    

    一点想法:

    突然发现不会做的(DP)和人生中好多事情都一样。总是缺乏迎难而上的勇气,总是在获得了不属于自己的东西之后沾沾自喜,总是在事情发生完了再追悔莫及。

    唉,人啊…

  • 相关阅读:
    94、二叉树的中序遍历 | JS
    102、二叉树的层序遍历 | JS
    111、二叉树的最小深度 | JS
    二叉树的先中后序遍历-JS非递归实现
    二叉树的先中后序遍历-JS递归实现
    深度和广度优先遍历-JS实现
    76、最小覆盖子串 | JS-字典
    extra1 二分查找与二叉判定树
    02 线性表的顺序存储
    原型、原型链、作用域、作用域链、闭包
  • 原文地址:https://www.cnblogs.com/pks-t/p/9407275.html
Copyright © 2011-2022 走看看