2
.子串
(substring.cpp/c/pas)
【问题描述】
有两个仅包含小写英文字母的字符串
A
和
B
。
现在要从字符串
A
中取出
k
个
互不重
叠
的非空子串,
然后把这
k
个子串按照其在字符串
A
中出现的顺序依次连接起来得到一
个新的字符串,
请问有多少种方案可以使得这个新串与字符串
B
相等?注意:
子串取出
的位置不同也认为是不同的方案
。
【输入格式】
输入文件名为
substring.in
。
第一行是三个正整数
n
,
m
,
k
,分别表示字符串
A
的长度,字符串
B
的长度,以及问
题描述中所提到的
k
,每两个整数之间用一个空格隔开。
第二行包含一个长度为
n
的字符串,表示字符串
A
。
第三行包含一个长度为
m
的字符串,表示字符串
B
。
【输出格式】
输出文件名为
substring.out
。
输出共一行,包含一个整数,表示所求方案数。
由于答案可能很大,所以这里要求输
出答案对
1,000,000,007
取模的结果。
【输入输出样例
1
】
substring.in
substring.out
6 3 1
aabaab
aab
2
见选手目录下
substring/substring1.in
与
substring/substring1.ans
。
【输入输出样例
2
】
substring.in
substring.out
6 3 2
aabaab
aab
7
见选手目录下
substring/substring2.in
与
substring/substring2.ans
。
【输入输出样例
3
】
substring.in
substring.out
6 3 3
aabaab
aab
7
见选手目录下
substring/substring3.in
与
substring/substring3.ans
。
【输入输出样例说明】
所有合法方案如下:
(加下划线的部分表示取出的子串)
样例
1
:
aab
aab / aab
aab
样例
2
:
a ab
aab /
a
aba
ab
/ a
a
ba
ab
/ aab
a ab
aa b
aab /
aa
baa
b
/ aab
aa b
样例
3
:
a a b
aab /
a a
baa
b
/
a
ab
a
a
b
/
a
aba
a
b
a
a
b
a
a
b
/ a
a
ba
a
b
/ aab
a
a
b
【输入输出样例
4
】
见选手目录下
substring/substring4.in
与
substring/substring4.ans
。
【数据规模与约定】
对于第
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
。
#include<cstdio>
#include<cstring>
const int mod=1000000007;
int dp[2][210][210][2];
char a[1010],b[210];
int main()
{
int i,j,k,m,n,l,p,q,x,y,z;
scanf("%d%d%d",&n,&m,&l);
scanf("%s",a+1);
scanf("%s",b+1);
dp[0][0][0][0]=dp[1][0][0][0]=1;
for (i=1;i<=n;i++)
{
for (j=1;j<=m;j++)
for (k=1;k<=l;k++)
{
dp[i&1][j][k][0]=dp[i&1^1][j][k][0];
if (a[i]==b[j])
{
dp[i&1][j][k][1]=(dp[i&1^1][j-1][k][1]+dp[i&1^1][j-1][k-1][0])%mod;
dp[i&1][j][k][0]=(dp[i&1][j][k][0]+dp[i&1][j][k][1])%mod;
}
}
for (j=1;j<=m;j++)
for (k=1;k<=l;k++)
dp[i&1^1][j][k][0]=dp[i&1^1][j][k][1]=0;
}
printf("%d\n",dp[n&1][m][l][0]);
}