Bad practice:
\ (dp [i] [j ] [k] [1/2] \) represents the i-th position of a string up using \ (K \) substring matching string prior to b j-th position is selected and the current i or the number of programs have not been selected because the current only and \ (i-1 \) related, so the first dimension can be scrolled.
When considering the transfer \ (a [i] == b [j] \) when, \ (DP [Val] [J] [K] [0] = (DP [Val ^. 1] [J] [K] [0 ] + dp [Val ^ 1] [j] [k] [1])% Mo \) , because I do not choose this position, he must be able to match from one location to use the j and k transferred from sub-string .
I is selected from this position, \ (DP [Val] [J] [K] [. 1] = ((DP [Val ^. 1] [J-. 1] [K-. 1] [0] + DP [Val ^. 1] [J-. 1] [K] [. 1])% Mo + DP [Val ^. 1] [J-. 1] [K-. 1] [. 1])% Mo \) , as he may be, and one composed of the same sub string, can also become a new substring.
When \ (a [i]! = B [j] \) , I chose this location is that I can not finally match, the value 0. If you do not choose to and on the same case.
#include<queue>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mo=1e9+7;
int n,m,p;
char a[1007],b[207];
int dp[2][1007][207][2];//dp[i][j][k][1/2]表示到a串的第i位置为止使用了k个子串匹配到b串的前j个且当前i位置选还是没选的方案数,第一位可以滚动
int main()
{
scanf("%d%d%d",&n,&m,&p);
scanf("%s",a+1);
scanf("%s",b+1);
dp[0][0][0][0]=1;//初值
int val=0;
for(int i=1;i<=n;i++)
{
val^=1;//奇数为1,偶数为0
dp[val][0][0][0]=1;
for(int j=1;j<=min(i,m);j++)
{
for(int k=1;k<=min(j,p);k++)
{
if(a[i]==b[j])
{
dp[val][j][k][0]=(dp[val^1][j][k][0]+dp[val^1][j][k][1])%mo;
dp[val][j][k][1]=((dp[val^1][j-1][k-1][0]+dp[val^1][j-1][k][1])%mo+dp[val^1][j-1][k-1][1])%mo;
}
else
{
dp[val][j][k][1]=0;//选了一个不匹配的点
dp[val][j][k][0]=(dp[val^1][j][k][0]+dp[val^1][j][k][1])%mo;
}
}
}
}
printf("%d\n",(dp[n&1][m][p][0]+dp[n&1][m][p][1])%mo);
return 0;
}