首页 > 其他分享 >P2679 子串

P2679 子串

时间:2022-12-25 16:44:33浏览次数:39  
标签:子串 int P2679 scanf 不选 字符串

P2679 子串

题意:

给出两个仅含小写字母的字符串 \(A\) 和 \(B\) 要求从 \(A\) 中取出 \(k\) 个互不重叠的非空子串,然后把这 \(k\) 个子串按照其在字符串 \(A\) 中的顺序依次连接起来形成新的字符串。

求有多少种方案可以使得这个新字符串和字符串 \(B\) 相等?

思路:

定义 \(f[i][j][k]\) ,为遍历到第 \(i\) 个字符,取出了 \(k\) 个子串,这 \(k\) 个子串,匹配到 \(B\) 字符串的第 \(j\) 个字符,划分为匹配的时候当前是成为一个新的子串,还是和之前的合并。但是合并的时候,必须先前面也是匹配的,所以考虑再加一个维度,标记第 \(i\) 个点是否选入。定义 \(f[i][j][k][h]\) :为遍历到 \(A\) 串的第 \(i\) 个位置使用了 \(k\) 个子串匹配了 \(B\) 的前 \(j\) 个字符,第 \(i\) 个位置选或不选的方案数。

划分依据为 第 \(i\) 个选或者不选

  • 当 \(a_i = b_j\) 时
    • 当前不选:\(f_{i,j,k,0} = f_{i - 1,j,k,0} + f_{i - 1,j,k,1}\)
    • 当前选:\(f_{i,j,k,1} = f_{i - 1,j - 1,k - 1,0} + f_{i - 1,j - 1,k - 1,1}\)
  • 当 \(a_i \not = b_j\) 时
    • 不选情况同上
    • 没办法选,\(f_{i,j,k,1} = 0\)

发现空间太大了,然后观察公式,发现只需要用到 \(i - 1\) 所以可以滚动,注意这里因为更新 \(k\) 时会用到 \(i -1\) 的 \(k\) 所以不能自我滚动。

实现:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3 + 5, M = 205, mod = 1e9 + 7;
char a[N], b[M];
ll f[2][M][M][2];
int main()
{
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    scanf("%s", a + 1);
    scanf("%s", b + 1);
    f[1][0][0][0] = f[0][0][0][0] = 1;
    // 遍历到 a 的哪个位置
    for (int i = 1; i <= n; i++)
    { // 匹配到 b 的哪个位置
        for (int j = 1; j <= m; j++)
            // 分成了几个子串
            for (int h = 1; h <= k; h++)
            {
                // 当前不匹配
                f[i & 1][j][h][0] = (f[(i & 1) ^ 1][j][h][0] + f[(i & 1) ^ 1][j][h][1]) % mod;

                // 当前匹配
                if (a[i] == b[j])
                {
                    // 另为一段
                    f[i & 1][j][h][1] = (f[(i & 1) ^ 1][j - 1][h - 1][0] + f[(i & 1) ^ 1][j - 1][h - 1][1]) % mod;
                    // 和之前的合并为一段
                    f[i & 1][j][h][1] = (f[i & 1][j][h][1] + f[(i & 1) ^ 1][j - 1][h][1]) % mod;
                }
                else
                    f[i & 1][j][h][1] = 0;
            }
    }

    printf("%lld\n", (f[n & 1][m][k][1] + f[n & 1][m][k][0]) % mod);

    return 0;
}

标签:子串,int,P2679,scanf,不选,字符串
From: https://www.cnblogs.com/zxr000/p/17004204.html

相关文章

  • 洛谷 P2679 [NOIP2015 提高组]子串
    \(70pts\):记\(sub_A(i)\)表示\(A\)的前\(i\)个字符构成的子串,相应地,\(sub_B(i)\)为\(B\)的前\(i\)个字符构成的子串。设\(f(i,j,k)\)表示在\(sub_A(i......
  • 3. 无重复字符的最长子串
    3.无重复字符的最长子串给定一个字符串s,请你找出其中不含有重复字符的最长子串的长度。输入:s="abcabcbb"输出:3解释:因为无重复字符的最长子串是"abc",所......
  • 查找子串
    #查找子串需求:查找一个字符串中是否包含某个关键词(查找子串问题)是很常见的操作。比如:给定一句话s,查找s中是否包含某关键词。in操作符如果只是为了判断s中是否包含麦叔......
  • leetcode-最长回文子串
    给你一个字符串s,找到s中最长的回文子串。如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。 示例1:输入:s="babad"输出:"bab"解释:"aba"同样是符合题意的答......
  • [LeetCode]005-最长回文子串
    >>传送门题目给你一个字符串s,找到s中最长的回文子串。如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。示例示例1输入:s="babad"输出:"bab"解释:"ab......
  • [LeetCode]003-无重复字符的最长子串
    >>>传送门题目给定一个字符串s,请你找出其中不含有重复字符的最长子串的长度。示例示例1输入:s="abcabcbb"输出:3解释:因为无重复字符的最长子串是"abc",......
  • 洛谷 P1020 导弹拦截(递增子串 DP )
    题目大意:有一个数列,我们要获取一组子串,这个子串必须单调不增。问:(1)最长我们可以获取多长的这种子串(2)这个数列中最多有多少种这种子串解题思路:其中问题一是很典型的DP问题,最......
  • 洛谷 P1233 木棍加工(贪心,递增子串DP)
    题目大意:有矩形A1,A2......An.每个矩形有长宽w,h。现在已知cost:(1)若矩形a的w,h小于矩形b的w,h,那么没有cost(2)其它情况cost+1.现在已知矩形A1,A2...,问怎么得到最少cost.解题思......
  • 力扣---5. 最长回文子串
    给你一个字符串s,找到s中最长的回文子串。示例1:输入:s="babad"输出:"bab"解释:"aba"同样是符合题意的答案。示例2:输入:s="cbbd"输出:"bb"提示:   1<=s.length<=......
  • LeetCode 3_无重复字符的最长子串
    LeetCode3:无重复字符的最长子串题目给定一个字符串s,请你找出其中不含有重复字符的最长子串的长度。示例1:输入:s="abcabcbb"输出:3解释:因为无重复字符......