#dp#洛谷 2679 子串
题目
有两个仅包含小写英文字母的字符串 \(A\) 和 \(B\)。
现在要从字符串 \(A\) 中取出 \(k\) 个互不重叠的非空子串,然后把这 \(k\) 个子串按照其在字符串 \(A\) 中出现的顺序依次连接起来得到一个新的字符串。请问有多少种方案可以使得这个新串与字符串 \(B\) 相等?
注意:子串取出的位置不同也认为是不同的方案。
分析
设\(dp[i][j]\)表示当前匹配到字符串\(B\)的第\(i\)个位置,
且当前为字符串\(A\)的第\(j\)个子串的方案数,
那就是新开一个子串或者是这个子串继续匹配,
所以用前缀和优化就可以了
代码
#include <cstdio>
#define rr register
using namespace std;
const int mod=1000000007; char s1[1001],s2[201];
int dp[201][201],n,m,k,s[201][201];
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
signed main(){
scanf("%d%d%d%s%s",&n,&m,&k,s1+1,s2+1);
dp[0][0]=1;
for (rr int i=1;i<=n;++i)
for (rr int j=m;j>=1;--j)
for (rr int p=k;p>=1;--p)
dp[j][p]=mo(dp[j][p],s[j][p]=(s1[i]==s2[j])?mo(s[j-1][p],dp[j-1][p-1]):0);
return !printf("%d",dp[m][k]);
}