Codevs 4560 NOIP2015 D2T2 子串

> 4560 NOIP2015 D2T2 子串
 时间限制: 1 s
 空间限制: 128000 KB
 题目等级:黄金 Gold
题目描述 Description
有两个仅包含小写英文字母的字符串A和B。现在要从字符串A中取出k个互不重叠的非空子串,然后把这k个子串按照其在字符串A中出现的顺序依次连接起来得到一个新的字符串,请问有多少种方案可以使得这个新串与字符串B相等?注意:子串取出的位置不同也认为是不同的方案。
输入描述 Input Description
第一行是三个正整数n,m,k,分别表示字符串A的长度,字符串B的长度,以及问题描述中所提到的k,每两个整数之间用一个空格隔开。 
第二行包含一个长度为n的字符串,表示字符串A。 第三行包含一个长度为m的字符串,表示字符串B。
输出描述 Output Description
输出共一行,包含一个整数,表示所求方案数。由于答案可能很大,所以这里要求输出答案对1,000,000,007取模的结果。
样例输入 Sample Input
【Input1】
6 3 1 
aabaab 
aab
【Input2】
6 3 2 
aabaab 
aab
【Input3】
6 3 3 
aabaab 
aab
样例输出 Sample Output
【Output1】
2
【Output2】
7
【Output3】
7
数据范围及提示 Data Size & Hint
对于第1组数据:1≤n≤5001≤m≤50,k=1; 
对于第2组至第3组数据:1≤n≤5001≤m≤50,k=2; 
对于第4组至第5组数据:1≤n≤5001≤m≤50,k=m; 
对于第1组至第7组数据:1≤n≤5001≤m≤501≤k≤m; 
对于第1组至第9组数据:1≤n≤10001≤m≤1001≤k≤m; 
对于所有10组数据:1≤n≤10001≤m≤2001≤k≤m。
/*
方案数DP+滚动数组优化.
f[i][j][p][]表示A串前i个字符B串前j个字符组成k个贡献的方案数.
(最后一维对当前字符用不用讨论). 
当前考虑两种状态:两个字符相等.
                 两个字符不等.
关于取模的问题相关:(a+b+c)%p=((a+b)%p+c)%p.
*/
#include<iostream>
#include<cstdio>
#define mod 1000000007
#define MAXN 1001
#define MAXM 201
using namespace std;
int f[2][MAXM][MAXM][2],n,m,k;
char s1[MAXN],s2[MAXM];
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-48,ch=getchar();
    return x*f;
}
int main()
{
    n=read();m=read();k=read();
    for(int i=1;i<=n;i++)  cin>>s1[i];
    for(int i=1;i<=m;i++)  cin>>s2[i];
    f[0][0][0][0]=f[1][0][0][0]=1;
    for(int i=1;i<=n;i++)
      for(int j=1;j<=min(i,m);j++)
        for(int p=1;p<=k;p++){
            int now=i&1,last=(i-1)&1;
            if(s1[i]==s2[j]) f[now][j][p][1]=((f[last][j-1][p][1]+f[last][j-1][p-1][0])%mod
                             +f[last][j-1][p-1][1])%mod,
                             f[now][j][p][0]=(f[last][j][p][0]+f[last][j][p][1])%mod;
            else f[now][j][p][1]=0,f[now][j][p][0]=(f[last][j][p][0]+f[last][j][p][1])%mod;; 
        }
    printf("%d",(f[n&1][m][k][0]%mod+f[n&1][m][k][1]%mod)%mod);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值