您的位置:首页 > 其它

Noip 2015 D2T2 子串(动态规划)

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

-----------------------------------------------------------------------------分割线-------------------------------------------------------------------------------------------------

f[i,j,k] (当前匹配到第k组,匹配完成第j位且最后一位是a[i])        s[i,j,k]=∑f[x,j,k](0<x<=i)前缀和

f[i,j,k]=0(a[i]<>b[j])当前位不相同

f[i,j,k]=s[i-1,j-1,k-1](a[i]=b[j]) and (a[i-1]<>b[j-1])前一位不相同

f[i,j,k]=s[i-1,j-1,k-1]+f[i-1,k-1,k](a[i]=b[i]) and (a[i-1]=b[j-1])

此题需要(空间)循环数组(时间)前缀和的优化方可AK

const
model=1000000007;
var
ans:qword;
a,b:array[1..1000] of char;
f,s:array[0..1000,0..1,1..200] of qword;
i,j,k,ki,ji,n,m:longint;
procedure p1;
begin
assign(input,'substring.in');
assign(output,'substring.out');
reset(input);
rewrite(output);
end;
procedure p2;
begin
close(input);
close(output);
end;
begin
p1;
readln(n,m,k);
for i:=1 to n do read(a[i]);readln;
for i:=1 to m do read(b[i]);readln;
for i:=1 to n do begin
if a[i]=b[1] then f[i,1,1]:=1 else f[i,1,1]:=0;
s[i,1,1]:=s[i-1,1,1]+f[i,1,1];
end;
for j:=2 to m do
for ki:=1 to k do begin
ji:=j and 1;
for i:=0 to n do begin s[i,ji,ki]:=0;f[i,ji,ki]:=0;end;
for i:=j to n-m+j do begin
if a[i]<>b[j] then f[i,ji,ki]:=0
else begin
if ki>1 then f[i,ji,ki]:=s[i-1,ji xor 1,ki-1];
if a[i-1]=b[j-1] then f[i,ji,ki]:=(f[i,ji,ki]+f[i-1,ji xor 1,ki]) mod model;
end;
s[i,ji,ki]:=(s[i-1,ji,ki]+f[i,ji,ki]) mod model;
end;
end;
writeln(s[n,m and 1,k]);
p2;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: