题面

看到求方案数,还要对 \(1000000007\ (1e9+7)\) 取模,一般这样的问题都要考虑 动态规划

我们设 \(dp_{i,j,k,0/1}\) 表示 \(A_{1\dots i}\) 中选取 \(k\) 个子串,与 \(B_{1\dots j}\) 匹配,且 \(A_{i}\) 选 / 不选的方案数。

分情况讨论转移:

  • 若 \(A_i = B_j\),

    • \(dp_{i,j,k,0} = dp_{i-1,j,k,0}+dp_{i-1,j,k,1}\)。

      • 不选 \(A_i\) 就说明 \(A_{1\dots i - 1}\) 已经与 \(B_{1\dots j}\) 匹配上了,那么方案数就是 \(A_{i-1}\) 选 / 不选的方案数之和;
    • \(dp_{i,j,k,1}=dp_{i-1,j-1,k,1}+dp_{i-1,j-1,k-1,0}+dp_{i-1,j-1,k-1,1}\)。
      • 第一种情况,将 \(A_i\) 接到 \(A_{i-1}\) 的后面,且 \(A_{i-1}\) 在第 \(k\) 个子串,必须选择 \(A_{i-1}\),直接加上方案数。
      • 第二种情况,如果不选择 \(A_{i-1}\),那么 \(A_i\) 就必须作为第 \(k\) 个子串,\(A_{i-1}\) 前面的子串只能有 \(k-1\) 个。
      • 第三种情况,选择 \(A_{i-1}\),并且新开一个长度为 \(1\) 的子串 \(A_i\)。
  • 若 \(A_i \neq B_j\),
    • \(dp_{i,j,k,0}=dp_{i-1,j,k,0}+dp_{i-1,j,k,1}\)。

      • 不选择 \(A_i\) 的方案数就是 \(A_{1\dots i-1}\) 已经和 \(B_{1\dots j}\) 匹配上的方案数,实质上就是 \(A_{i-1}\) 选 / 不选的方案数。其实和 \(A_i=B_j\) 的情况是一样的。
    • \(dp_{i,j,k,1} = 0\)。
      • 如果要选择 \(A_i\),且 \(A_{1\dots i}\) 与 \(B_{1\dots j}\) 匹配上,那么没有一种方案符合这种要求,方案数为 \(0\)。

讨论有些复杂,可以自己在纸上再推一遍。

然而这样做空间会爆炸。

我们发现每一次转移 \(i\) 时的状态只与 \(i-1\) 的状态有关,于是我们可以开一个滚动数组把这一维的空间优化成 \(2\)。开滚动数组只需要将第一维全部 & 1 即可。

边界初始化 \(dp_{0,0,0,0}=dp_{1,0,0,0}=1\),因为选 \(0\) 个子串时任何的 \(A_{1\dots i}\) 都可以与空串匹配,因为此时什么都不要取。

这样做我们就可以通过本题了。

注意开 \(\text{long long}\)。

#include <bits/stdc++.h>

using namespace std;

const int mod = 1000000007;

int n, m, K;
long long dp[2][203][203][2]; //注意开 long long
char a[1003], b[203]; int main()
{
cin >> n >> m >> K;
scanf("%s%s", a + 1, b + 1);
dp[0][0][0][0] = dp[1][0][0][0] = 1; //边界条件
for (int i = 1; i <= n; i+=1)
for (int j = 1; j <= m; j+=1)
for (int k = 1; k <= K; k+=1) //转移
if (a[i] == b[j])
dp[i & 1][j][k][1] = (dp[(i - 1) & 1][j - 1][k][1] + dp[(i - 1) & 1][j - 1][k - 1][0] + dp[(i - 1) & 1][j - 1][k - 1][1]) % mod,
dp[i & 1][j][k][0] = (dp[(i - 1) & 1][j][k][0] + dp[(i - 1) & 1][j][k][1]) % mod;
else
dp[i & 1][j][k][1] = 0,
dp[i & 1][j][k][0] = (dp[(i - 1) & 1][j][k][1] + dp[(i - 1) & 1][j][k][0]) % mod;
cout << (dp[n & 1][m][K][0] + dp[n & 1][m][K][1]) % mod << endl; //输出最后答案
return 0;
}

题解【洛谷P2679】[NOIP2015]子串的更多相关文章

  1. 【题解】洛谷P2679 [NOIP2015TG] 子串(DP+滚动数组)

    次元传送门:洛谷P2679 思路 蒟蒻一开始并没有思路而去看了题解 我们发现对于两个字串的位置 我们只需要管他们匹配成功或者匹配失败即可 f[i][j][k] 记录当前 a[i]不论等不等于b[j] ...

  2. [洛谷P2408]不同子串个数

    题目大意:给你一个字符串,求其中本质不同的字串的个数 题解:同[洛谷P4070][SDOI2016]生成魔咒,只要最后再输出就行了 卡点:无 C++ Code: #include <cstdio ...

  3. 题解 洛谷P5018【对称二叉树】(noip2018T4)

    \(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...

  4. 题解 洛谷 P3396 【哈希冲突】(根号分治)

    根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...

  5. 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)

    题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...

  6. 题解-洛谷P4229 某位歌姬的故事

    题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...

  7. 题解-洛谷P4724 【模板】三维凸包

    洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...

  8. 题解-洛谷P4859 已经没有什么好害怕的了

    洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...

  9. 题解-洛谷P5217 贫穷

    洛谷P5217 贫穷 给定长度为 \(n\) 的初始文本 \(s\),有 \(m\) 个如下操作: \(\texttt{I x c}\),在第 \(x\) 个字母后面插入一个 \(c\). \(\te ...

  10. 题解 洛谷 P2010 【回文日期】

    By:Soroak 洛谷博客 知识点:模拟+暴力枚举 思路:题目中有提到闰年然后很多人就认为,闰年是需要判断的其实,含有2月29号的回文串,前四位是一个闰年那么我们就可以直接进行暴力枚举 一些小细节: ...

随机推荐

  1. jdk升级后Eclipse无法启动问题

    overview: 今日安装jdk11,设置好环境变量后,eclipse无法运行,由于项目依赖原因,不想更新eclipse的版本. 我的jdk是1.8,在将环境变量设回1.8后依然无法运行.在多次尝试 ...

  2. mitmproxy--Cannot establish TLS with client (sni: e.crashlytics.com): TlsException("(-1, 'Unexpected EOF')",) 解决办法

    按崔哥(https://cuiqingcai.com/5391.html)的安装步骤一步步下来,会报这个错误: Cannot establish TLS with client (sni: e.cra ...

  3. C# 多线程的阻塞和继续-ManaulResetEvent的使用

    在工作中,会遇到需要多线程处理相应的业务需求,最典型的包括Socket的通信. 多线程处理里,就会考虑到,哪个线程先运行,哪个线程后运行的情况. 这里我介绍一下,使用ManualResetEvent类 ...

  4. Linux_simpl shell-利用Shell脚本for循环输出系统中的用户及其Shell

    [root@localhost ~]# vim user.sh 1 #!/bin/bash 2 for i in `cut -d ":" -f1 /etc/passwd`; 3 d ...

  5. Linux发行版Ubuntu下的Python开发环境的配置

    linux下的Python安装, 首先我们需要使用都Shell一系列的命令(前面的linux基础可不是白学的哦!) 1.更新软件安装源地址 sudo apt-get update apt-get,是一 ...

  6. CF #622 div.2

    序 ~ieowjf~~ 真的只有老邱在支持我吗(雾 #622 T1 此题做法显然,但是,不知为何,就是会评测机有小问题...无语 上 SingerCoder 的码,不知为何,我的码风总是毒瘤 #inc ...

  7. 简单聊聊CSS中的3D技术之“立方体”

    简单聊聊CSS中的3D技术之“立方体” 大家好,我是今天的男一号,我叫小博主. 今天来聊一下我在前端“逆战班”学习中遇到的颇为有趣的3D知识.前端学习3周,见识稀疏,在下面的分享中如有不对的地方请大家 ...

  8. open Live Writer 代码插件安装

    1,第一步:下载open live writer插件,下载地址:http://www.cnblogs.com/memento/p/5995173.html 2,拷贝文件到Plugins目录(自己建立) ...

  9. PHP Strings

    <?php //1. how to use mail function //create short variable names $name=$_POST['name']; $email=$_ ...

  10. linux基础之磁盘管理与文件系统

    上面一篇文章(https://www.cnblogs.com/ckh2014/p/7224851.html)介绍了硬盘的基本结构,那么一块磁盘如何应用取存储数据呢? 它的步骤是这样的: 识别硬盘 -- ...