题意
有 两个字符串,要从 中选出 个子串,按原顺序排列后形成 。求方案数。
的长度为 , 。
题解
用 表示取到 ,选了 个子串的方案数。可以枚举当前子串的长度 ,这样要求 和 完全匹配。显然 中取的上一个位置可以在 中任选,方程式为:
可以用前缀和优化掉,用 表示关于 的前缀和,则方程式可化为:
这样每次枚举 时间会爆炸。可以发现当 时, 比 多了 ,方程式化为:
时间没问题了,但空间还是会爆,所以用滚动数组优化。
#include<bits/stdc++.h>
#define ha 1000000007
using namespace std;
inline int read()
{
char ch=getchar(); int f=1,x=0;
while (ch<'0' || ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
while (ch>='0' && ch<='9') { x=x*10+ch-'0'; ch=getchar(); }
return f*x;
}
char x[1005],y[205];
int n,m,k,f[205][205],g[205][205];
signed main()
{
n=read(); m=read(); k=read();
scanf("%s%s",x+1,y+1);
g[0][0]=1;
for (int i=1;i<=n;i++)
{
for (int j=min(i,m);j;j--)
{
for (int l=min(k,j);l;l--)
{
if (x[i]==y[j]) f[j][l]=(f[j-1][l]+g[j-1][l-1])%ha;
else f[j][l]=0;
g[j][l]=(g[j][l]+f[j][l])%ha;
}
}
}
return !printf("%d",g[m][k]);
}