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取模的结果。
【输入输出样例3】
见选手目录下substring/substring1.in与substring/substring1.ans。 见选手目录下substring/substring3.in与substring/substring3.ans。
一看到这题,就想到了DP。很明显可以看到三维的dp状态,dp[i,j,k],表示A串到i位置,B串到j位置,已经用了k个串的方案数。
var标签:子串,do,NOIP2015Day2T2,mo,substring,ans,字符串,now From: https://blog.51cto.com/u_15888102/5878315
mo,n,m,k,i,j,p,now,pre,s:longint;ans:int64;a,b:ansistring;
f:array[0..1,0..1000,0..1000]of longint;
begin
mo:=1000000007;
readln(n,m,k);
readln(a);
readln(b);
for i:=1 to n do if a[i]=b[1] then f[0,i,1]:=1;
for p:=2 to m do
begin
pre:=1-now;
for j:=1 to k do
begin
s:=0;
for i:=1 to n do
begin
s:=(s+f[now,i-1,j-1])mod mo;
if a[i]=b[p] then f[pre,i,j]:=(f[now,i-1,j]+s)mod mo
else f[pre,i,j]:=0;
end;
end;
now:=pre;
end;
for i:=1 to n do ans:=(ans+f[now,i,k])mod mo;
writeln(ans);
end.