NOIP2015提高组T2 子串

来源:互联网 发布:c语言中各类数据 编辑:程序博客网 时间:2024/06/05 12:29

题目描述

有两个仅包含小写英文字母的字符串 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.


原创粉丝点击