题目大意

  有两个仅包含小写英文字母的字符串 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,...)$转移。
  • 最后输出结果的时候别忘了取模呀!
  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5.  
  6. #define ll long long
  7. #define F(i, j, k, t) DP[(i) & 1][j][k][t]
  8. const int MAX_N = 1010, MAX_M = 210;
  9. const ll P = 1e9 + 7;
  10. char A[MAX_N], B[MAX_M];
  11. ll DP[2][MAX_M][MAX_M][2];
  12. int N, M, K;
  13.  
  14. ll Dp()
  15. {
  16. A[0] = '*', B[0] = '-';
  17. for (int i = 0; i <= N; i++)
  18. {
  19. memset(DP[i + 1 & 1], 0, sizeof(DP[i + 1 & 1]));
  20. F(i, 0, 0, 0) = 1;
  21. for (int j = 0; j <= M; j++)
  22. for (int k = 0; k <= K; k++)
  23. {
  24. //t = 1
  25. if (j > 0)
  26. F(i + 1, j, k, 0) = (F(i + 1, j, k, 0) + F(i, j, k, 1)) % P;
  27. if (A[i + 1] == B[j + 1])
  28. {
  29. F(i + 1, j + 1, k, 1) = (F(i + 1, j + 1, k, 1) + F(i, j, k, 1)) % P;
  30. F(i + 1, j + 1, k + 1, 1) = (F(i + 1, j + 1, k + 1, 1) + F(i, j, k, 1)) % P;
  31. }
  32. //t = 0
  33. if (j > 0)
  34. F(i + 1, j, k, 0) = (F(i + 1, j, k, 0) + F(i, j, k, 0)) % P;
  35. if (A[i + 1] == B[j + 1])
  36. F(i + 1, j + 1, k + 1, 1) = (F(i + 1, j + 1, k + 1, 1) + F(i, j, k, 0)) % P;
  37. }
  38. }
  39. return (F(N, M, K, 0) + F(N, M, K, 1)) % P;
  40. }
  41.  
  42. int main()
  43. {
  44. scanf("%d%d%d\n", &N, &M, &K);
  45. scanf("%s", A + 1);
  46. scanf("%s", B + 1);
  47. printf("%lld\n", Dp());
  48. return 0;
  49. }

  

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. Crash reporter

    A crash reporter is a software application whose function is to identify report crash details and to ...

  2. 网络编程基础_4.2TCP-客户端

    TCP-客户端 #include <stdio.h> // 1. 包含必要的头文件和库, 必须位于 windows之前 #include <WinSock2.h> #pragm ...

  3. vue-element-admin使用常见问题

    一.vue-element-admin添加快捷导航 这个组件是基于vue-i18n因此,首先在项目中安装i18n npm install --save vue-i18n 然后main.js中引入 im ...

  4. 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList

    package algorithms; import java.util.ArrayList; import java.util.Stack; /** * public class ListNode ...

  5. [转]Js获取当前日期时间及其它操作

    转载自:http://www.cnblogs.com/carekee/articles/1678041.html Js获取当前日期时间及其它操作 var myDate = new Date();myD ...

  6. UVA-12333 Revenge of Fibonacci(竖式加法模拟 & 字典树)

    题目: 给出一个斐波那契数字的前缀,问第一个有这个前缀的数字在斐波那契数列中是第几个. 思路: 紫书提示:本题有一定效率要求.如果高精度代码比较慢,可能会超时. 利用滚动数组和竖式加法来模拟斐波那契相 ...

  7. Python数据分析与展示(1)-数据分析之表示(2)-NumPy数据存取与函数

    NumPy数据存取与函数 数据的CSV文件存取 CSV文件 CSV(Comma-Separated Value,逗号分隔值) CSV是一种常见的文件格式,用来存储批量数据. 将数据写入CSV文件 np ...

  8. Codeforces Educational Codeforces Round 17 Problem.A kth-divisor (暴力+stl)

    You are given two integers n and k. Find k-th smallest divisor of n, or report that it doesn't exist ...

  9. [bzoj2242][SDOI2011][计算器] (Baby-Step-Giant-Step+快速幂+exgcd)

    Description 你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数: 3.给 ...

  10. 个人常用git命令

    最近开始使用git,将自己常用git命令做一个简单归纳,便于记忆. 初始化及配置 git init:初始化资料库 git config --global user.name 'xxx':配置用户名 g ...