• LibreOJ 2424 子串


    题目链接:LibreOJ 2424 子串

    题目大意:

    题解:
    (dp[j][k])表示字符串(A)判断到第(i)个字符且一定取第(i)个字符,组成字符串(B)的前(j)个字符,用了(k)个子串的方案数。
    (DP[j][k])表示字符串(A)判断到第(i)个字符但不一定取第(i)个字符,组成字符串(B)的前(j)个字符,用了(k)个子串的方案数。

    1. (A[i-1] eq B[j-1]),则(dp[j][k] = 0)

    2. (A[i-1]=B[j-1]),可以选择将(A[i-1])加在(A[i-2])后面算作一个子串,则此时(A[i-2])必须可取且要一定取,方案数为(dp[j-1][k]);若将(A[i-1])算作一个新的子串,则(A[i-2])不一定取,方案数为(DP[j-1][k-1]),则状态转移方程为:

    [left{egin{aligned}dp[j][k] &= dp[j - 1][k] + DP[j - 1][k - 1],&A[i-1]= B[j-1]\dp[j][k] &= 0,&A[i-1] eq B[j-1]end{aligned} ight. ]

    [DP[j][k] = sum_{1}^{i} dp[j][k] ]

    看到这肯定发现(i)所在的那一维被压缩了,所以在(j)的循环里,(j)是从(m)(1)递减更新答案的(可以联想(01)背包压缩成一维数组)。

    #include <iostream>
    #include <string>
    using namespace std;
    #define N 1010
    const int mod = 1e9 + 7;
    
    int dp[210][210], DP[210][210], n, m, t;
    string a, b;
    
    int main() {
        ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
        cin >> n >> m >> t;
        cin >> a >> b;
        dp[0][0] = DP[0][0] = 1;
        for (int i = 1; i <= n; ++i) {
            for (int j = m; j >= 1; --j) {
                for (int k = 1; k <= t; ++k) {
                    if (a[i - 1] == b[j - 1]) {
                        dp[j][k] = (dp[j - 1][k] + DP[j - 1][k - 1]) % mod;
                        DP[j][k] = (DP[j][k] + dp[j][k]) % mod;
                    } else {
                        dp[j][k] = 0;
                    }
                }
            }
        }
        cout << DP[m][t];
        return 0;
    }
    
  • 相关阅读:
    docker OCI runtime
    docker 非root用户修改mount到容器的文件出现“Operation not permitted
    清除canvas画布内容--点擦除+线擦除
    js实现存储对象的数据结构hashTable和list
    学习ES6的全部特性
    页面重绘与重排版的性能影响
    测试css3的动画效果在display:none的时候不耗费性能
    stroke和fill顺序对绘图的影响
    css样式学习小知识
    统一事件监听
  • 原文地址:https://www.cnblogs.com/IzumiSagiri/p/15068164.html
Copyright © 2020-2023  润新知