【题目描述】

有两个仅包含小写英文字母的字符串A和B。现在要从字符串A中取出k个互不重叠的非空子串,然后把这k个子串按照其在字符串A中出现的顺序依次连接起来得到一个新的字符串,请问有多少种方案可以使得这个新串与字符串B相等?注意:子串取出的位置不同也认为是不同的方案。

由于答案可能很大,所以这里要求输出答案对1,000,000,007取模的结果。

【样例输入1】

6 3 1

aabaab

aab

【样例输出1】

2

【样例输入2】

6 3 2

aabaab

aab

【样例输出2】

7

【样例输入3】

6 3 3

aabaab

aab

【样例输出3】

7

【数据规模与约定】

对于100%的数据:1≤n≤1000,1≤m≤200,1≤k≤m。

【解法】

还好吧……一个DP……不过细节比较多,难度不小。

我们令f[i][j][k][0/1]表示A串用了前i个字符,B串已覆盖前j个字符,目前为止已经选了k个子串,最后的0/1表示A串的这个字符选了没有(0没选,1选了)。

为了得出状态转移方程,我们分情况讨论:

先看f[i][j][k][1](当前位选了),显然当且仅当a[i]=b[j]的时候它才有意义,否则f[i][j][k][1]=0。

到这个状态有三种方法:

1. 上一位没有选,新开一个子串

2. 上一位选了,延续这个子串

3. 上一位选了,但是仍然新开一个子串

因此,我们有

f[i][j][k][1]=f[i-1][j-1][k-1][0]+f[i-1][j-1][k][1]+f[i-1][j-1][k-1][1]。

状态转移方程中的三项分别对应上述三种情况。注意,因为我们规定了A的这一位必须选(因为状态的最后一维是1),所以所有前驱状态一定是f[i-1][j-1][…][…]。

然后讨论另一种情况:这个字符不选。

这个比较简单,到这个状态有两种方法:

1. 上一位没有选,现在仍然不选

2. 上一位选了,结束这个子串

因此,我们有

f[i][j][k][0]=f[i-1][j][k][0]+f[i-1][j][k][1]。

合起来就是

f[i][j][k][1]=f[i-1][j-1][k-1][0]+f[i-1][j-1][k][1]+f[i-1][j-1][k-1][1](a[i]=b[j])

f[i][j][k][1]=0(a[i]!=b[j])

f[i][j][k][0]=f[i-1][j][k][0]+f[i-1][j][k][1]

状态转移方程有了,边界也容易确定:f[0][0][0][0]=1。至于最终答案,显然是f[n][m][k][0]+f[n][m][k][1]。

这里有O(nmk)个状态,转移是O(1)的,因此总复杂度O(nmk),完全够用(毕竟常数不大)。

然后,注意一些可能越界的问题(j/k=0的时候不要j/k-1),再用滚动数组压掉第一维,就可以AC了。

贴个代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=,maxm=;
int n,m,c,i=,f[][maxm][maxm][];
char a[maxn],b[maxm];
int main(){
#define MINE
#ifdef MINE
freopen("2015substring.in","r",stdin);
freopen("2015substring.out","w",stdout);
#endif
scanf("%d%d%d %s %s",&n,&m,&c,a+,b+);
f[][][][]=;
for(int d=;d<=n;d++,i=!i)for(int j=;j<=d&&j<=m;j++)for(int k=;k<=j&&k<=d&k<=c;k++){
f[i][j][k][]=;
if(d->=j){
(f[i][j][k][]+=f[!i][j][k][])%=;
(f[i][j][k][]+=f[!i][j][k][])%=;
}
f[i][j][k][]=;
if(j&&a[d]==b[j]){
if(k){
(f[i][j][k][]+=f[!i][j-][k-][])%=;
(f[i][j][k][]+=f[!i][j-][k-][])%=;
}
(f[i][j][k][]+=f[!i][j-][k][])%=;
}
}
printf("%d\n",(f[!i][m][c][]+f[!i][m][c][])%);
#ifndef MINE
printf("\n--------------------DONE--------------------\n");
for(;;);
#endif
return ;
}

【后记】

去年联赛的Day2 T2……难度还可以,主要是状态表示和转移方程比较麻烦,也不太好想,有些细节问题略恶心。

很久没刷过DP了……自己DP本来就弱,不过好歹自己想出来了解法,也算是个安慰吧(我才不会说其实我已经从各种渠道知道了这题的复杂度是O(nmk)的)。

为了这题废了一节课……努力吧……

[NOIP2015] 子串substring 题解的更多相关文章

  1. NOIP2015子串[序列DP]

    题目背景 无 题目描述 有两个仅包含小写英文字母的字符串 A 和 B.现在要从字符串 A 中取出 k 个互不重 叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一 个 ...

  2. Vijos1982 NOIP2015Day2T2 子串 substring 动态规划

    子串 (substring.cpp/c/pas) 题目链接 [问题描述]有两个仅包含小写英文字母的字符串 A 和 B.现在要从字符串 A 中取出 k 个 互不重叠 的非空子串,然后把这 k 个子串按照 ...

  3. Vijos1425子串清除 题解

    Vijos1425子串清除 题解   描述: 我们定义字符串A是字符串B的子串当且仅当我们能在B串中找到A串.现在给你一个字符串A,和另外一个字符串B,要你每次从B串中从左至右找第一个A串,并从B串中 ...

  4. NOIP2015 子串 (DP+优化)

    子串 (substring.cpp/c/pas) [问题描述] 有两个仅包含小写英文字母的字符串 A 和 B.现在要从字符串 A 中取出 k 个 互不重 叠 的非空子串,然后把这 k 个子串按照其在字 ...

  5. LOJ2424 NOIP2015 子串 【DP】*

    LOJ2424 NOIP2015 子串 LINK 题目大意是给你两个序列,在a序列中选出k段不重叠的子串组成b序列,问方案数 首先我们不考虑相邻的两段,把所有相邻段当成一段进行计算 然后设dpi,j, ...

  6. [NOIP2015]子串 题解

    题目描述 有两个仅包含小写英文字母的字符串A和B. 现在要从字符串A中取出k个互不重叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一个新的字符串,请问有多少种方案可 ...

  7. 题解【洛谷P2679】[NOIP2015]子串

    题面 看到求方案数,还要对 \(1000000007\ (1e9+7)\) 取模,一般这样的问题都要考虑 动态规划. 我们设 \(dp_{i,j,k,0/1}\) 表示 \(A_{1\dots i}\ ...

  8. NOIP2015 子串

    #149. [NOIP2015]子串 有两个仅包含小写英文字母的字符串 AA 和 BB. 现在要从字符串 AA 中取出 kk 个互不重叠的非空子串,然后把这 kk 个子串按照其在字符串 AA 中出现的 ...

  9. [DP][NOIP2015]子串

    子串 题目描述 有两个仅包含小写英文字母的字符串 A 和 B. 现在要从字符串 A 中取出 k 个 互不重叠 的非空子串, 然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一个新的 ...

随机推荐

  1. 调用startActivityForResult,onActivityResult无响应的解决办法

    三种情况: 1.执行startActivityForResult,没等到被调用的 Activity 返回,onActivityResult() 就被执行了.找了很久,终于通过小道消息得知,这与 Act ...

  2. $this->display输出模板

    1.public function index(){ $this->display() } // 默认输出的是index.html模板 2.public function index(){ $t ...

  3. jquery特效收藏

    js网址收藏: 懒人图库:www.lanrentuku.com 懒人之家:http://www.lanrenzhijia.com/jquery/list_5_2.html 1.UI下载:http:// ...

  4. jquery mobile 图片自适应问题

    解决办法: 加入一段css <link rel="stylesheet" href="http://jquerymobile.com/demos/1.1.0/doc ...

  5. 替换所有的cell的右侧箭头

    写个UITableViewCell的分类重写这个方法 - (void)didMoveToSuperview { [super didMoveToSuperview]; // 全局替换右侧箭头 if ( ...

  6. Exception Handling in ASP.NET Web API webapi异常处理

    原文:http://www.asp.net/web-api/overview/error-handling/exception-handling This article describes erro ...

  7. 缓存 HttpContext.Current.Cache和HttpRuntime.Cache的区别

    先看MSDN上的解释: HttpContext.Current.Cache:为当前 HTTP 请求获取Cache对象. HttpRuntime.Cache:获取当前应用程序的Cache.  我们再用. ...

  8. 浅谈JavaScript中的能力检测

    引言 我们知道,各个版本的浏览器有着许多不一致性.理想状态下,应该是所有的浏览器都提供一套标准的API接口.但是现实中,各个版本的浏览器存在的怪癖非常多,我们通常都是使用客户端检测来作为补救措施.但是 ...

  9. 软删除脏数据job笔记

    某次处理一个case,发现线上库里有很多数据有问题.于是决定写一个job来将有问题的数据软删除掉.涉及到的两条SQL语句如下: <select id="loadTSKTVBillDai ...

  10. mysql 导入sql文件,source命令

    转自:http://blog.sina.com.cn/s/blog_610997850100mwv8.html 今天碰到个问题要用phpmyadmin导入1G的数据,但是在怎么都导入不了,用命令行就可 ...