【題意分析】
這種dp題也就是按照套路來,先設一個四維的狀態:dp[i][j][k][l]
就是第一個串前i個,第二個串前j個,取了k段,第二個串當前位置取不取(0不取1取)的方案總數
計數dp嘛,分類討論:
如果枚舉的位置兩個字符相同,那麼就表明可以取或不取
//對第二個naive方程的解釋:這個字符取了,可能上個字符取了,連成一段或者另起一段,或者上個字符不取,那麼必定另起一段。
如果不同,那麼就只能不取
就好了,然後很明顯第一維可以滾動掉(大部分計數dp都可以滾動掉一維),就可以過了
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#define MAXN 1010
#define MAXM 205
#define qy 1000000007
using namespace std;
char s1[MAXN], s2[MAXN];
int dp[2][MAXM][MAXM][2], n, m, K, now, pre;
int main () {
scanf ("%d%d%d", &n, &m, &K), scanf ("%s", s1 + 1), scanf ("%s", s2 + 1);
dp[0][0][0][0] = dp[1][0][0][0] = 1, now = 0, pre = 1;
for (register int i = 1; i <= n; i++) {
now ^= 1, pre ^= 1;
for (register int j = 1; j <= m; j++)
for (register int k = 1; k <= K; k++) {
if (s1[i] == s2[j]) {
dp[now][j][k][0] = (dp[pre][j][k][0] + dp[pre][j][k][1]) % qy;
dp[now][j][k][1] = ((dp[pre][j - 1][k - 1][0] + dp[pre][j - 1][k - 1][1]) % qy + dp[pre][j - 1][k][1]) % qy;
}
else {
dp[now][j][k][0] = (dp[pre][j][k][0] + dp[pre][j][k][1]) % qy;
dp[now][j][k][1] = 0;
}
}
}
return printf ("%d\n", (dp[n & 1][m][K][0] + dp[n & 1][m][K][1]) % qy), 0;
}