P2679 [NOIP2015 提高组] 子串
P2679 [NOIP2015 提高组] 子串
0x01 题意
给出字符串A和B,在A中取\(k\)个不重叠的子串,按原来的顺序排列后与B相同,求方案数
0x02 解
DP
设\(f[i][j][p]\)为A字符串匹配到\(i\),B字符串匹配到\(j\)时,取\(p\)个子串且\(A_i\)为最后一位匹配成功的方案数,很好转移
为了求答案,我们需要\(f\)关于\(i\)的前缀和,定义为\(g\),有\(f[i][j][p]=\sum_Lg[i-L][j-L][p-1]\)
递推优化\(f[i][j][p]=f[i-1][j-1][p]+g[i-1][j-1][p-1]\)
因为只和上一项有关,所以可以优化成二维
0x03 码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1010,M=210,Mod=1000000007;
int f[N][M],n,m,k,g[N][N];
char a[N],b[M];
signed main(){
cin>>n>>m>>k;
scanf("%s%s",a+1,b+1);
g[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=min(m,i);j>=1;j--)
for(int p=min(k,j);p>=1;p--){
f[j][p]=a[i]==b[j]?(f[j-1][p]+g[j-1][p-1])%Mod:0;
g[j][p]=(g[j][p]+f[j][p])%Mod;
}
cout<<g[m][k];
return 0;
}