NOIP2015提高组T2 子串

题目描述

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

输入

第一行是三个正整数 n,m,k,分别表示字符串 A 的长度,字符串 B 的长度,以及问题描述中所提到的 k,每两个整数之间用一个空格隔开。 第二行包含一个长度为 n 的字符串,表示字符串 A。 第三行包含一个长度为 m 的字符串,表示字符串 B。

输出

输出共一行,包含一个整数,表示所求方案数。由于答案可能很大,所以这里要求输出答案对 1,000,000,007 取模的结果。

样例输入

6 3 1
aabaabaab

6 3 2
aabaabaab

样例输出

2

7

HINT


这题在推出状态后转移时竟然改变了状态的意义,吐血地打了1个小时。

下面要郑重地写一下状态。

f[i][j][k]表示B串的1~i已被A串的1~j匹配完,此时匹配了k个子串,且A串的第j位匹配B串的第i位,此时的方案数。

则f[i][j][k]=f[i-1][1~j-1][k-1]+f[i-1][j-1][k];前提是a[j]=b[i].

但这样的转移是O(nm^2k)的,还是会超时

所以我们可以记下来f[i-1][1~j-1][k-1] 的和啊。

这样转移就是O(1)的了,再开一维滚动防止爆内存。时间复杂度O(nmk).

这才将这题解决,可是考试时在这题上花了太多时间qwq,记住吧。


var 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.


你可能感兴趣的:(动态规划,NOIP,OI)