题目大意

  有两个仅包含小写英文字母的字符串 A 和 B。现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一 个新的字符串,请问有多少种方案可以使得这个新串与字符串 B 相等?注意:子串取出 的位置不同也认为是不同的方案。对于所有 10 组数据:1≤n≤1000,1≤m≤200,1≤k≤m。

题解

  本题的错误解法是定义状态$f(i, j, k)$为字符串$A$的前$i$个字符,字符串$B$的前$j$个字符已经匹配完,且已经分了$k$块时的方案最多为多少,状态转移为$f(i+1,j,k)+=f(i,j,k),若A_{i+1}=B_{j+1},则f(i+1,j+1,k)+=f(i,j,k),f(i+1,j+1,k+1)+=f(i,j,k)$。

  本算法错在我们没有记录$f(i,j,k)$中$i$有没有选在子串中,这使各类关于$k$的转移,如$f(i+1,j+1,k)+=f(i,j,k)$等,不成立。

  所以正确解法为定义状态$f(i,j,k,0)$表示第$i$位选在子串中,$f(i,j,k,1)$表示没有选,这样就有递归式:$f(i+1,j,k,0)+=f(i,j,k,0),若A_{i+1}=B_{i+1},f(i+1,j+1,k+1,1)+=f(i,j,k,0)$;$f(i+1,j,k,0)+=f(i,j,k,1),若A_{i+1}=B_{i+1},f(i+1,j+1,k,1)+=f(i,j,k,1),f(i+1,j+1,k+1,1)+=f(i,j,k,1)$。初始条件$f(i,0,0,0)=1$

踩过的坑

  • 滚动数组每一次都要清空!
  • $j=0$时,只有$f(i,0,0,0)$有意义,其它都没有意义,所以$f(i,0,...)$不能向$f(i+1,0,...)$转移。
  • 最后输出结果的时候别忘了取模呀!
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; #define ll long long
#define F(i, j, k, t) DP[(i) & 1][j][k][t]
const int MAX_N = 1010, MAX_M = 210;
const ll P = 1e9 + 7;
char A[MAX_N], B[MAX_M];
ll DP[2][MAX_M][MAX_M][2];
int N, M, K; ll Dp()
{
A[0] = '*', B[0] = '-';
for (int i = 0; i <= N; i++)
{
memset(DP[i + 1 & 1], 0, sizeof(DP[i + 1 & 1]));
F(i, 0, 0, 0) = 1;
for (int j = 0; j <= M; j++)
for (int k = 0; k <= K; k++)
{
//t = 1
if (j > 0)
F(i + 1, j, k, 0) = (F(i + 1, j, k, 0) + F(i, j, k, 1)) % P;
if (A[i + 1] == B[j + 1])
{
F(i + 1, j + 1, k, 1) = (F(i + 1, j + 1, k, 1) + F(i, j, k, 1)) % P;
F(i + 1, j + 1, k + 1, 1) = (F(i + 1, j + 1, k + 1, 1) + F(i, j, k, 1)) % P;
}
//t = 0
if (j > 0)
F(i + 1, j, k, 0) = (F(i + 1, j, k, 0) + F(i, j, k, 0)) % P;
if (A[i + 1] == B[j + 1])
F(i + 1, j + 1, k + 1, 1) = (F(i + 1, j + 1, k + 1, 1) + F(i, j, k, 0)) % P;
}
}
return (F(N, M, K, 0) + F(N, M, K, 1)) % P;
} int main()
{
scanf("%d%d%d\n", &N, &M, &K);
scanf("%s", A + 1);
scanf("%s", B + 1);
printf("%lld\n", Dp());
return 0;
}

  

luogu2679 子串的更多相关文章

  1. [luogu2679] 子串 (多维dp)

    传送门 Description 有两个仅包含小写英文字母的字符串 A 和 B . 现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来 ...

  2. luogu2679 [NOIp2015]子串 (dp)

    设f[i][j][k][b]表示在A串第i位.这是第j组.B串第k位.i号选不选(b=0/1) 那么就有$f[i][j][k][1]=(A[i]==B[k])*(f[i-1][j-1][k][0]+f ...

  3. LeetCode[5] 最长的回文子串

    题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...

  4. 最长回文子串-LeetCode 5 Longest Palindromic Substring

    题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...

  5. C语言计算字符串子串出现的次数

    #include<stdio.h>#include<string.h>int substring(char *str,char *str1);//函数原型int main(vo ...

  6. [LeetCode] Longest Substring with At Most Two Distinct Characters 最多有两个不同字符的最长子串

    Given a string S, find the length of the longest substring T that contains at most two distinct char ...

  7. [LeetCode] Minimum Window Substring 最小窗口子串

    Given a string S and a string T, find the minimum window in S which will contain all the characters ...

  8. [LeetCode] Substring with Concatenation of All Words 串联所有单词的子串

    You are given a string, s, and a list of words, words, that are all of the same length. Find all sta ...

  9. [LeetCode] Longest Substring Without Repeating Characters 最长无重复子串

    Given a string, find the length of the longest substring without repeating characters. For example, ...

随机推荐

  1. 扩增子分析解读5物种注释 OTU表操作

    本节课程,需要先完成<扩增子分析解读>系列之前的操作 1质控 实验设计 双端序列合并 2提取barcode 质控及样品拆分 切除扩增引物 3格式转换 去冗余 聚类 4去嵌合体 非细菌序列 ...

  2. Java基础(六)--枚举Enum

    枚举: 刚开始项目中没怎么用过,只知道能够实现作为项目中类似定义Constant的功能,然后知道枚举实现的单例模式几乎是最优雅的,所以, 想要深入完整的了解一下 1.基本特性: Enum.values ...

  3. ThinkPHP---案例2--部门管理功能

    [一]部门列表展示 分析: ①控制器DeptController.class.php ②方法showList(不要使用list方法,因为list是关键词) ③模板文件:showList.html 下面 ...

  4. 洛谷——P2158 [SDOI2008]仪仗队

    P2158 [SDOI2008]仪仗队 找规律大水题嘛,如果你做过P1170 兔八哥与猎人 这题得到的规律是$a,b,c,d$,若$gcd(a-b,c-d)==1$ 那么$a,b$就能看到$c,d$ ...

  5. Python&机器学习总结(一)

    ① numpy中np.c_和np.r_ np.r_是按列连接两个矩阵,就是把两矩阵上下相加,要求列数相等,类似于pandas中的concat(). np.c_是按行连接两个矩阵,就是把两矩阵左右相加, ...

  6. JMeter测试websocket

    今天公司要测websocket,搞了一天踩了不少坑,关键是还没爬出来,BOSS让回家再理理思路,没办法到家就开干. 一.家里玩的还是2.1的,为了少踩坑,先下个JMeter5.1.1(他们说4版本也行 ...

  7. FJoi2017 1月20日模拟赛 交错和(等差数列+rmq)

    [题目描述] 无限循环数字串S由长度为n的循环节s构成.设s为12345(n=5),则数字串S为123451234512345… 设Si为S的第i位数字,在上面的例子中,S1=1,S2=2,S6=1. ...

  8. 从“菜鸟”码农到“资深”架构师,我到底经历了什么?--------http://baijiahao.baidu.com/s?id=1585813883835208757&wfr=spider&for=pc

    http://baijiahao.baidu.com/s?id=1585813883835208757&wfr=spider&for=pc

  9. (12)GrabCut前景提取

    import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread('opencv-python-foregr ...

  10. CodeForces 362C

    分析:首先我们要知道调用swap()函数的次数跟什么有关.可以观察发现在Insertion Sort里,当且仅当a[j](j∈[0,i)) > a[i]时会调用一次swap(),也就是说有多少个 ...