题目描述
有两个仅包含小写英文字母的字符串 A 和 B。现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一 个新的字符串,请问有多少种方案可以使得这个新串与字符串 B 相等?注意:子串取出 的位置不同也认为是不同的方案。
设
d(i,j,k)
表示字符串A前
i
个字符取出
设
首先
d(i,j,k)=d(i−1,j,k)
如果A[i]!=B[j]
f(i,j,k)=0
否则{
我们可以单独取出A[i]和B[j]匹配
d(i,j,k)+=d(i−1,j−1,k−1)
且
f(i,j,k)=d(i−1,j−1,k−1)
如果A[i-1]==B[j-1]我们还可以取出每一个以A[i]结尾的串和以B[i]结尾的串匹配。
d(i,j,k)+=f(i−1,j−1,k)
且
f(i,j,k)+=f(i−1,j−1,k)
}
再用滚动数组优化。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int mo=1e9+7;
int d[210][210],f[210][210];
int main(){
int n,m,u;
char s1[1010],s2[210];
cin>>n>>m>>u>>s1+1>>s2+1;
d[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=m;j>0;j--)
for(int k=u;k>0;k--){
if(s1[i]==s2[j]){
d[j][k]=(d[j][k]+d[j-1][k-1])%mo;
f[j][k]=d[j-1][k-1];
if(s1[i-1]==s2[j-1]){
d[j][k]=(d[j][k]+f[j-1][k])%mo;
f[j][k]=(f[j][k]+f[j-1][k])%mo;
}
}
else f[j][k]=0;
}
cout<<d[m][u]<<endl;
return 0;
}