NOIP2015DAY2T2子串
描述
有两个仅包含小写英文字母的字符串A和B。现在要从字符串A中取出k个互不重叠的非空子串,然后把这k个子串按照其在字符串A中出现的顺序依次连接起来得到一 个新的字符串,请问有多少种方案可以使得这个新串与字符串B相等?注意:子串取出 的位置不同也认为是不同的方案。
【数据规模与约定】 对于第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。
输入
输入文件名为substring.in。 第一行是三个正整数n,m,k,分别表示字符串A的长度,字符串B的长度,以及问 题描述中所提到的k,每两个整数之间用一个空格隔开。 第二行包含一个长度为n的字符串,表示字符串A。 第三行包含一个长度为m的字符串,表示字符串B。
输出
输出文件名为substring.out。 输出共一行,包含一个整数,表示所求方案数。由于答案可能很大,所以这里要求输 出答案对1,000,000,007取模的结果。
样例输入[复制]
6 3 1
aabaab
aab
样例2:
6 3 2
aabaab
aab
样例3:
6 3 3
aabaab
aab
样例输出[复制]
2
样例2:
7
样例3:
7
f[i][j][k]=f[i-1][j-1][k-1]+f[i-1][j-1][k]
s[i][j][k]=f[i-1][j-1][k-1]+s[i-1][j-1][k]
显然如果a[i]!=b[j]的话直接s[i][j][k]就是0
接下来我们考虑f[i][j][k]的转移,前提还是一样的
由于我现在的决策已经变成了选或者不选的问题了,已经与匹不匹配无关了
如果我选择这个进行匹配的话,如果是使用当前的字符,我们就要加上一定使用这个字符的方案数s[i][j][k],如果你说我选上并不匹配怎么办?注意如果本身不匹配那么s[i][j][k]是0,选上没有意义
如果我们选择不用的话,自然就直接由上一个状态转移过来f[i-1][j][k]
方程就是
f[i][j][k]=s[i][j][k]+f[i-1][j][k]
为什么我们这个没有判断说是a[i]==b[j]?因为与匹配无关,我们关心的是选上去的方案数的贡献和不选的贡献,为什么我们不在s里面解决?因为选与不选是一个状态,自成一家或者与前面混合又是一个状态,两个状态不能混在一起!!
最后发现数组不够用啊,我们尝试滚掉一维
为什么我们能滚掉一维?因为在写循环的时候我们是按i作为第一维,而第一维i使用完之后只会对i+1做出贡献,就是背包问题,于是我们就复用数组
至于滚掉一维数组后后面的循环顺序就应该倒过来,因为你要用之前的状态,如果你正向就会用到刚算好的状态造成重复(这也是多重背包的原理),就可以覆盖前面
还是照例总结一下
这道题其实告诉我如果有多个不同的状态(红字)就应该尝试分开他们来进行讨论,不要固执于使用一个数组,这些状态是交融但是不完全等同的,应该及时分开处理
记得取模
代码在下面了:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 char a[100000],b[10000]; 5 int f[1000][1000]; 6 int s[1000][1000];const int mod=1000000007; 7 int main() { 8 int n,m,k; 9 cin>>n>>m>>k; 10 for(int i=1; i<=n; i++)cin>>a[i]; 11 for(int i=1; i<=m; i++)cin>>b[i]; 12 f[0][0]=1; 13 for(int i=1;i<=n;i++){ 14 for(int j=m;j>=1;j--){ 15 for(int l=k;l>=1;l--){ 16 if(a[i]==b[j])s[j][l]=f[j-1][l-1]+s[j-1][l]; 17 else s[j][l]=0; 18 s[j][l]%=mod; 19 f[j][l]=f[j][l]+s[j][l]; 20 f[j][l]%=mod; 21 //cout<<s[j][l]<<" "<<f[j][l]<<" "<<j<<" "<<l<<endl; 22 } 23 } 24 } 25 cout<<f[m][k]; 26 return 0; 27 }
一道好题啊
转载于:https://www.cnblogs.com/saionjisekai/p/9653320.html
NOIP2015DAY2T2子串相关推荐
- Redis 笔记(03)— string类型(设置key、获取key、设置过期时间、批量设置获取key、对key进行加减、对key值进行追加、获取value子串)
字符串 string 是 Redis 最简单的数据结构.Redis 所有的数据结构都是以唯一的 key 字符串作为名称,然后通过这个唯一 key 值来获取相应的 value 数据.不同类型的数据结构的 ...
- 寻找一个字符串的重复子串 后缀数组
什么是后缀数组 令字符串 S=S[1]S[2]...S[n]S=S[1]S[2]...S[n]{\displaystyle S=S[1]S[2]...S[n]} , S[i,j]S[i,j]{\dis ...
- leetcode 3. Longest Substring Without Repeating Characters 最长非重复子串的长度 滑动窗口法
题目链接 根据我们之前介绍的滑动窗口法的解法: 滑动窗口法详解 leetcode 438. Find All Anagrams in a String 滑动窗口法 这题,我们不难解决,使用之前的模板. ...
- 求一个字符串中连续出现的次数最多的子串
求一个字符串中连续出现的次数最多的子串.例如字符串"abababc",最多连续出现的为ab,连续出现三次.要和求一个字符串中的最长重复子串区分开来,还是上面的字符串,那么最长的重复 ...
- 【牛客网】最长对称子串
给定一个字符串(数字或大小写字母), 找出最长的对称的子串(如有多个,输出任意一个). 例如: 输入:"abbaad" 输出:"abba" #include & ...
- 【leetcode】力扣刷题(3):无重复字符的最长子串(go语言)
一.问题描述 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 " ...
- 【动态规划】最长公共子序列与最长公共子串
1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...
- BZOJ1396:识别子串(SAM)
Description Input 一行,一个由小写字母组成的字符串S,长度不超过10^5 Output L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长. Sample I ...
- SPOJ 694 不同子串个数
一个论文题,求一个字符串有多少个不同的子串. 每个字符串可以看做一个后缀的前缀,然后,就转换为求每一个后缀中,不同的子串有多少. 每一个后缀,根据长度,可以提供len - sa[i] 个子串,但是,画 ...
最新文章
- RH系列linux上编译android2.3(gingerbread)
- Progressbar 实现从右向左 加载(逆向)
- 2021-09-26
- [文摘20070913]最好的消息
- struts2 的struts.properties配置详解
- java导出生成word(类似简历导出)
- word2003如何设置护眼模式_ERP系统上线,如何设置采购收货的模式,提升企业的采购效率...
- [html] 你有使用过meter标签吗?说说它的用途有哪些?
- Sudoku Extension UVALive - 4763
- Office文档上传后实时转换为PDF格式_图片文件上传后实时裁剪_实现在线预览Office文档
- WordPress 图片防盗链的方法
- sys.stdout.write与sys.sterr.write(一)
- 解决Mac osx AirPort: Link Down on en1. Reason 8 (Disassociated because station leaving)
- 苹果Mac专业的 Go 开发集成环境:JetBrains GoLand
- 破解极域电子教室密码
- 只会纯硬件,让我有点慌
- 三国演义主要人物个人经历
- (原创)直观了解通道混和器的校色作用
- 小鲲Python嘎嘎炫~day2
- java edt,Java Swing 学问篇 - EDT