您的位置:首页 > 其它

Luogu P2679 [NOIp提高组2015]子串

2017-08-14 13:43 239 查看
题目描述

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

设d(i,j,k)表示字符串A前i个字符取出k个子串组成字符串B的前j个字符的方案数。

设f(i,j,k)表示如果A[i]==b[j]且必须取A[i],值为字符串A前…方案数(同上),否则为0。

首先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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: