子串 [NOIP2015]
Description
有两个仅包含小写英文字母的字符串 A 和 B。现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一 个新的字符串,请问有多少种方案可以使得这个新串与字符串 B 相等?注意:子串取出 的位置不同也认为是不同的方案。
Input
第一行是三个正整数 n,m,k,分别表示字符串 A 的长度,字符串 B 的长度,以及问题描述中所提到的 k,每两个整数之间用一个空格隔开。
第二行包含一个长度为 n 的字符串,表示字符串 A。 第三行包含一个长度为 m 的字符串,表示字符串 B。
Output
输出共一行,包含一个整数,表示所求方案数。由于答案可能很大,所以这里要求输出答案对 1,000,000,007 取模的结果。
Sample Input
样例输入1:
6 3 1
aabaab
aab
样例输入2:
6 3 2
aabaab
aab
Sample Output
样例输出1:
2
样例输出2:
7
Hint
数据范围:
对于第 1 组数据:1≤n≤500,1≤m≤50,k=1;
对于第 2 组至第 3 组数据:1≤n≤500,1≤m≤50,k=2;
对于第 4 组至第 5 组数据:1≤n≤500,1≤m≤50,k=m;
对于第 1 组至第 7 组数据:1≤n≤500,1≤m≤50,1≤k≤m;
对于第 1 组至第 9 组数据:1≤n≤1000,1≤m≤100,1≤k≤m;
对于所有 10 组数据:1≤n≤1000,1≤m≤200,1≤k≤m。
Solution
这道题一看tm就是道DP题,而且第一感觉会很复杂
设状态
首先先来观察,我们设状态的话,要存储的应该有当前位置i,被匹配到的位置j,用了几个子串k(dp[i][j][k])
但我们发现还有一个棘手的问题,如何判断当前的是一个独立的子串还是连接到前面的子串
那么我们就要知道某一个位置是否被匹配,再加上一维[0/1]代表是否被匹配
状态转移
对于dp[i][j][k][0],他没被匹配,那匹配位置没变,子串个数没变,从i-1转移就是 dp[i-1][j][k][0]+dp[i-1][j][k][1]
对于dp[i][j][k][1],前提条件就是A[i]==B[j],满足条件后我们发现,它可以分别从 (1)前一位没被匹配 (2)前一位被匹配,这个字符连接到前面一个子串 (3)前一位没被匹配,这一个字符单独成为一个子串,那么转移方程为dp[i-1][j-1][k-1][0]+dp[i-1][j-1][k-1][1]+dp[i-1][j-1][k][1]
细节&优化
边界条件:dp[i][1][1][0]=sigma(j=1->i-1)(A[j]==B[1])(显然可以累计,不需要每次求) dp[i][1][1][1]=(A[i]==B[1])
dp[1000][200][200][2]的空间是显然爆炸的,由于只要用到前一维,可以滚一滚第一维
而每次计算完dp[i]后,要清空dp[i-1],否则会对dp[i+1]产生干扰(因为是滚动的)
Code
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define RG register int
#define rep(i,a,b) for(RG i=a;i<=b;i++)
#define per(i,a,b) for(RG i=a;i>=b;i--)
#define ll long long
#define inf (1<<30)
#define maxm 205
using namespace std;
const ll mo=;
int n,m,t,p,q;
ll sum;
ll dp[][maxm][maxm][];
char A[],B[maxm];
inline int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} int main()
{
n=read(),m=read(),t=read();
scanf("%s",A+);scanf("%s",B+);
p=,q=;
rep(i,,n)
{
swap(p,q);
dp[p][][][]=sum;
if(A[i]==B[]) dp[p][][][]=,sum++;
rep(j,,m)
rep(k,,t)
{
if(A[i]==B[j]) (dp[p][j][k][]=(dp[q][j-][k-][]+dp[q][j-][k][])%mo+dp[q][j-][k-][])%=mo;
dp[p][j][k][]=(dp[q][j][k][]+dp[q][j][k][])%mo;
}
rep(j,,m) rep(k,,t) dp[q][j][k][]=dp[q][j][k][]=;
}
cout<<(dp[p][m][t][]+dp[p][m][t][])%mo;
return ;
}
子串 [NOIP2015]的更多相关文章
- 刷题总结——子串(NOIP2015)
题目: 题目背景 NOIP2015 提高组 Day2 T2 题目描述 有两个仅包含小写英文字母的字符串 A 和 B .现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在 ...
- 子串 NOIP2015 D2T2 luoguP2679 字符串处理+DP
AC通道! 题目大意: 给定两个长度分别为 n 和 m 的字符串 A 和 B,选取 A 中的 k 个子串,使这 k 个子串按照先后顺序连接起来后等于 B 子串. 输入输出样例 输入 #1 6 3 ...
- 洛谷P2679 子串 [noip2015] dp
正解:dp 解题报告: 感觉是道dp好题啊,所以就写了个题解 代码实现难度低,思维难度大,像我这种思维僵化傻逼选手只想到了爆搜+组合数学... 其实是道很妙的dp题!好趴也没有多妙主要大概是妙在想到了 ...
- NOIP2015子串[序列DP]
题目背景 无 题目描述 有两个仅包含小写英文字母的字符串 A 和 B.现在要从字符串 A 中取出 k 个互不重 叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一 个 ...
- NOIP2015 子串
#149. [NOIP2015]子串 有两个仅包含小写英文字母的字符串 AA 和 BB. 现在要从字符串 AA 中取出 kk 个互不重叠的非空子串,然后把这 kk 个子串按照其在字符串 AA 中出现的 ...
- UOJ149 【NOIP2015】子串
本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权! [问题描述]有两个仅包含小写英文字母的字符串 A ...
- 4560 NOIP2015 D2T2 子串
4560 NOIP2015 D2T2 子串 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 有两 ...
- Codevs 4560 NOIP2015 D2T2 子串
> 4560 NOIP2015 D2T2 子串 时间限制: 1 s 空间限制: 128000 KB 题目等级:黄金 Gold 题目描述 Description 有两个仅包含小写英文字母的字符串A ...
- LOJ2424 NOIP2015 子串 【DP】*
LOJ2424 NOIP2015 子串 LINK 题目大意是给你两个序列,在a序列中选出k段不重叠的子串组成b序列,问方案数 首先我们不考虑相邻的两段,把所有相邻段当成一段进行计算 然后设dpi,j, ...
随机推荐
- K3 WISE 开发插件《SQL语句WHERE查询-范围查询/模糊查询》
0.存储过程开头变量定义 @FBeginDate varchar(10), --单据起始日期 @FEndDate varchar(10), --单据截止日期. @FItemID varchar(50) ...
- 使用 cacti 监控 windows 服务器硬盘的 I/O 状况
https://blog.csdn.net/m0_37814112/article/details/80742433
- TagCanvas 插件
TagCanvas是一个基于HTML5 Canvas技术开发的标签云动画.还提供一个以jQuery插件形式实现的版本. 它支持文本和图片两种格式,能够以Sphere, hcylinder 或 vcyl ...
- ubuntu下的“用vim打开中文乱码,用cat打开正常显示”的解决方法
转载 系统环境:ubuntu10.04 vim gvim完全安装 问题:终端下vim中的汉字为乱码,网上搜索了一些解决方案.但是奇怪的是,这些方法都不能实现gvim的菜单和文中汉字,终端vim下的文中 ...
- 常用js正则表达式大全
常用js正则表达式大全.一.校验数字的js正则表达式 1 数字:^[0-9]*$ 2 n位的数字:^\d{n}$ 3 至少n位的数字:^\d{n,}$ 4 m-n位的数字:^\d{m,n}$ 5 零和 ...
- cookie实现刷新不变化树形菜单
通过设置cookie来保存树形菜单的状态,在页面加载时重新读取cookie来设置菜单. 菜单的HTML结构: <div class="treemenu"> <ul ...
- Zabbix微信报警触发
(1) 企业应用-创建应用 1.除了对个人添加微信报警之外,还可以添加不同管理组,接受同一个应用推送的消息, 成员账号,组织部门ID,应用Agent ID,CorpID和Secret, ...
- .net core跨平台的文件路径
windows下路径为:"xxxx\\yyyy" linux路径下为:"xxxx/yyyy" 用Path.Combine("xxxx",&q ...
- Excel ——多表关联查询-vlookup
一.分组 需求: 在B列的右侧添加一列[消费分组]对B列的[月分组水平]进行分组,原始数据如下: 公式:在 C2 输入:“=VLOOKUP(B2,$E$1:$G$4,2,1)”,下拉填充. 提示:VL ...
- pyqt text browser 设置文本
pyqt text browser 设置文本 setHtml(u"Html") setPlainText(u"纯文本") setText(u"文本\n ...