首页 > 其他分享 >P2679 [NOIP2015 提高组] 子串

P2679 [NOIP2015 提高组] 子串

时间:2022-10-25 15:02:25浏览次数:51  
标签:子串 std NOIP2015 int P2679 cin 字符串 个字符

题意:

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

思路:

  • 状态设计:

    A串的第 i 位,匹配到了B串第 j 位,使用了k个子串。

    可以得出dp数组:f[i][j][k][u]。

  • 状态转移:

    第 i 个字符如果跟第 j 个字符相同, 则对于该字符有两种决策, 可以使用或者不使用
    1.当前使用 f[i][j][k][1] = f[i - 1][j - 1][k][1] + f[i - 1][j - 1][k - 1][0] + f[i - 1][j - 1][k - 1][0];
    2: 当前不用 f[i][j][j][0] = f[i - 1][j][k][1] + f[i - 1][j][k][0];
    第 i 个字符如果跟第 j 个字符相同, 则对于该字符只有一种决策, 不使用
    f[i][j][j][0] = f[i - 1][j][k][1] + f[i - 1][j][k][0];
    当前第i个字符不能使用 所以
    f[i][j][k][1] = 0

  • 内存优化:
    对于上述内存为 1000 * 200 * 200 * 2, 内存肯定不会爆。
    我们发现状态转移只用到了 i 和 i - 1。
    所以可以将一维优化到 2
    对于 i - 1 可以表示成 (i - 1) & 1
    对于 i 可以表示成 i & 1

代码:

        

#include <bits/stdc++.h>
#define int long long
const int MOD = 1e9 + 7;
int f[2][220][220][2];

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr), std::cout.tie(nullptr);
    int n, m, q;
    std::cin >> n >> m >> q;
    std::string a, b;
    std::cin >> a >> b;
    a = '!' + a;
    b = '!' + b;
    f[0][0][0][0] = 1;
    f[1][0][0][0] = 1;

    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            for (int k = 1; k <= q; ++k) {
                if (a[i] == b[j]) {
                    f[i & 1][j][k][1] = (f[(i - 1) & 1][j - 1][k][1] + f[(i - 1) & 1][j-1][k-1][0]) + f[(i - 1) & 1][j - 1][k - 1][1];
                    f[i & 1][j][k][0] = f[(i - 1) & 1][j][k][1] + f[(i - 1) & 1][j][k][0];
                    f[i & 1][j][k][1] %= MOD;
                    f[i & 1][j][k][0] %= MOD;
                }

                else {
                    f[i & 1][j][k][0] = f[(i - 1) & 1][j][k][1] + f[(i - 1) & 1][j][k][0];
                    f[i & 1][j][k][1] = 0;
                    f[i & 1][j][k][0] %= MOD;
                }
            }
        }
    }

    std::cout << (f[n & 1][m][q][1] + f[n & 1][m][q][0]) % MOD << '\n';
    return 0;
}

 

标签:子串,std,NOIP2015,int,P2679,cin,字符串,个字符
From: https://www.cnblogs.com/MCJ-YMR/p/16824826.html

相关文章

  • 回文子串对(扩展kmp-kmp与回文子串)
    Problem1回文子串对(manacher.cpp/c/pas)【题目描述】给定一长度为n的小写字母串,求有多少对回文子串,它们的交集非空。一对回文子串的交集非空:[a,b]、[c,d](a≠c或b≠d)为2......
  • 5. 最长回文子串
    给你一个字符串s,找到s中最长的回文子串。示例1:输入:s="babad"输出:"bab"解释:"aba"同样是符合题意的答案。示例2:输入:s="cbbd"输出:"bb"提示:1<=s.length<=10......
  • 最长回文子串
    输入:s="babad"输出:"bab"解释:"aba"同样是符合题意的答案。classSolution:deflongestPalindrome(self,s:str)->str:palindrome=""#中心......
  • #yyds干货盘点# LeetCode 腾讯精选练习 50 题:最长回文子串
    题目:给你一个字符串s,找到s中最长的回文子串。 示例1:输入:s="babad"输出:"bab"解释:"aba"同样是符合题意的答案。示例2:输入:s="cbbd"输出:"bb"代码实现:publicclassSo......
  • NOIP2015普及组复赛参考解析
    目录P2669[NOIP2015普及组]金币P2670[NOIP2015普及组]扫雷游戏P2671[NOIP2015普及组]求和P2672[NOIP2015普及组]推销员题目传送P2669[NOIP2015普及组]金......
  • leetcode 最长回文子串
    constcountSubstrings=(s)=>{conststrLen=s.length;letnumOfPalindromicStr=0;//初始化一个二维数组letdp=Array.from(Array(strLen),()=>A......
  • 51Nod 1088 最长回文子串——————Manacher,马拉车算法
    ​​51Nod1088最长回文子串​​基准时间限制:1秒空间限制:131072KB分值:0难度:基础题回文串是指这种左右对称的字符串。输入一个字符串,输出里最长回文子串的长度。I......
  • #yyds干货盘点# 面试必刷TOP101:最小覆盖子串
    1.简述:描述给出两个字符串s 和t,要求在s 中找出最短的包含t 中所有字符的连续子串。数据范围:,保证s和t字符串中仅包含大小写英文字母要求:进阶:空间复杂度  ,时间复杂......
  • Python index()方法:检测字符串中是否包含某子串
    同find()方法类似,index()方法也可以用于检索是否包含指定的字符串,不同之处在于,当指定的字符串不存在时,index()方法会抛出异常。index()方法的语法格式如下:str.index(......
  • Python find()方法:检测字符串中是否包含某子串
    find()方法用于检索字符串中是否包含目标字符串,如果包含,则返回第一次出现该字符串的索引;反之,则返回-1。find()方法的语法格式如下:str.find(sub[,start[,end]])此格式......