当前位置: 首页 > news >正文

题解:洛谷 P2679 [NOIP 2015 提高组] 子串

【题目来源】

洛谷:P2679 [NOIP 2015 提高组] 子串 - 洛谷

【题目描述】

有两个仅包含小写英文字母的字符串 \(A\)\(B\)

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

注意:子串取出的位置不同也认为是不同的方案。

【输入】

第一行是三个正整数 \(n,m,k\),分别表示字符串 \(A\) 的长度,字符串 \(B\) 的长度,以及问题描述中所提到的 \(k\),每两个整数之间用一个空格隔开。

第二行包含一个长度为 \(n\) 的字符串,表示字符串 \(A\)

第三行包含一个长度为 \(m\) 的字符串,表示字符串 \(B\)

【输出】

一个整数,表示所求方案数。

由于答案可能很大,所以这里要求输出答案对 \(1000000007\) 取模的结果。

【输入样例】

6 3 1 
aabaab 
aab

【输出样例】

2

【解题思路】

image

【算法标签】

《洛谷 P2679 子串》#字符串# #动态规划,dp# #枚举# #NOIP提高组# #O2优化# #2015#

【代码详解】

// 70分版本
#include <bits/stdc++.h>
using namespace std;#define int long long  // 定义int为long long类型
const int MOD = 1000000007;  // 定义模数// 四维DP数组:
// dp[i][j][k][0] - 前i个s1和前j个s2使用k次匹配且不以s1[i]结尾的方案数
// dp[i][j][k][1] - 前i个s1和前j个s2使用k次匹配且以s1[i]结尾的方案数
int dp[505][55][55][2];  int n, m, x;        // n: s1长度, m: s2长度, x: 最大匹配次数
string s1, s2;      // 输入的两个字符串signed main()
{// 输入参数和字符串cin >> n >> m >> x >> s1 >> s2;// 在字符串前添加空格,使索引从1开始s1 = " " + s1;s2 = " " + s2;// 初始化DP数组:空字符串有1种匹配方式for (int i = 0; i <= n; i++){dp[i][0][0][0] = 1;}// 动态规划填表for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){for (int k = 1; k <= x; k++){// 不选择s1[i]作为匹配结尾的情况dp[i][j][k][0] = (dp[i-1][j][k][0] + dp[i-1][j][k][1]) % MOD;// 选择s1[i]作为匹配结尾的情况if (s1[i] == s2[j]){dp[i][j][k][1] = (dp[i-1][j-1][k][1] + dp[i-1][j-1][k-1][1] + dp[i-1][j-1][k-1][0]) % MOD;}else{dp[i][j][k][1] = 0;  // 字符不匹配,方案数为0}}}}// 输出结果:总方案数取模cout << (dp[n][m][x][0] + dp[n][m][x][1]) % MOD;return 0;
}
// 100分版本,使用滚动数组
#include <bits/stdc++.h>
using namespace std;#define int long long  // 定义int为long long类型
const int MOD = 1000000007;  // 定义模数// 滚动数组优化后的四维DP数组:
// dp[0/1][j][k][0] - 前i个s1和前j个s2使用k次匹配且不以s1[i]结尾的方案数
// dp[0/1][j][k][1] - 前i个s1和前j个s2使用k次匹配且以s1[i]结尾的方案数
int dp[2][205][205][2];  int n, m, x;        // n: s1长度, m: s2长度, x: 最大匹配次数
string s1, s2;      // 输入的两个字符串signed main()
{// 输入参数和字符串cin >> n >> m >> x >> s1 >> s2;// 在字符串前添加空格,使索引从1开始s1 = " " + s1;s2 = " " + s2;// 初始化DP数组:空字符串有1种匹配方式for (int i = 0; i <= 2; i++){dp[i][0][0][0] = 1;}// 动态规划填表(使用滚动数组优化空间)for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){for (int k = 1; k <= x; k++){// 不选择s1[i]作为匹配结尾的情况dp[1][j][k][0] = (dp[0][j][k][0] + dp[0][j][k][1]) % MOD;// 选择s1[i]作为匹配结尾的情况if (s1[i] == s2[j]){dp[1][j][k][1] = (dp[0][j-1][k][1] + dp[0][j-1][k-1][1] + dp[0][j-1][k-1][0]) % MOD;}else{dp[1][j][k][1] = 0;  // 字符不匹配,方案数为0}}}// 滚动数组:将当前状态复制到前一状态memcpy(dp[0], dp[1], sizeof(dp[0]));}// 输出结果:总方案数取模cout << (dp[1][m][x][0] + dp[1][m][x][1]) % MOD;return 0;
}

【运行结果】

6 3 1 
aabaab 
aab
2
http://www.jsqmd.com/news/397085/

相关文章:

  • 论文降AI后导师说风格变了怎么办?保持个人写作风格的实用指南
  • 题解:洛谷 P1439 两个排列的最长公共子序列
  • php条件语句(混合php的if语句和js编程)
  • 题解:洛谷 P4933 大师
  • 基于LSTM的共享单车需求预测研究
  • 题解:洛谷 P2285 [HNOI2004] 打鼹鼠
  • 题解:洛谷 P1020 [NOIP 1999 提高组] 导弹拦截
  • 携程任我行礼品卡回收实操步骤 - 京顺回收
  • 研究生开题答辩前如何确保论文AI率合格?导师不会告诉你的实操指南
  • neovim配置python插件支持环境 —— Pynvim 环境搭建 —— Pynvim安装
  • 期刊投稿也要查AI了?学术期刊AIGC检测现状与对策
  • Gemini 3.1 Pro在这个平台便宜到离谱,编程能力竟然超过GPT-5.2和Opus 4.6
  • MySQL几种count比
  • 2026年广州AI获客服务商赋能实体经济标杆企业TOP10榜单:技术与产业深度融合的领航者 - 野榜精选
  • 在K8s集群中部署Traefik并验证Python HTTP服务
  • 深入浅出 K8s 内外部通信:全场景方案解析与生产实践
  • 2026年热压/烫金/丝印皮牌工艺行业优质供应商TOP10推荐:聚焦全链条服务能力,助力品牌价值升级 - 野榜精选
  • 深入解析Nginx反向代理多服务时静态资源路径冲突的根源与解决方案
  • 2026年,探寻有抗衰老功效的保健品,保健品/抗衰老片,保健品食品选哪家 - 品牌推荐师
  • 2026年2月无管道新风机品牌TOP10榜单:技术创新与场景适配性双维度评选 - 野榜精选
  • 对数额外空间的森林判定
  • OpenJDK和Oracle JDK有什么区别和联系?
  • 探寻2026可长期服用能抗疲劳的保健品,抗衰老片/保健品,保健品产品哪家好 - 品牌推荐师
  • Linux 多线程编程入门:线程栈、TLS、互斥锁与条件变量详解
  • C++的多态是如何体现的?一篇文章搞懂C++虚函数机制与常见问题
  • 【Linux】sudo 命令提升权限的使用技巧
  • HTTP 协议发展详解:从 HTTP/1 到 HTTP/3
  • 大模型应用开发:从选型到部署的核心考量
  • 探索ABAQUS刀盘切削竹材有限元模型
  • Prompt,除了使用外,你了解其核心原理么?