P2679 [NOIP2015 提高组] 子串 题解

发布时间 2023-10-23 23:33:55作者: xxxxxxxb
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD = 1000000007;
int n,m,k,dp[205][205][2];
char A[1005],B[205];
signed main() {
    cin.tie(0)->sync_with_stdio(0);
    cin >> n >> m >> k;
    cin >> (A+1) >> (B+1);
    for(int i = 1;i <= n;++i) {
        dp[0][0][0] = 1;
        for(int j = min(i,m);j >= 1;--j) {
            for(int p = min(k,j);p >= 1;--p) {
                dp[j][p][0] = (dp[j][p][1] + dp[j][p][0]) % MOD;
                if(A[i] == B[j])
                    dp[j][p][1] = (dp[j-1][p-1][0] + dp[j-1][p-1][1]+ dp[j-1][p][1])%MOD;
                else 
                    dp[j][p][1] = 0; //
            }
        }
    }
    cout << (dp[m][k][0]+dp[m][k][1]) % MOD << '\n';
    return 0;
}
//设dp[i][j][k][0/1] : A前i个,B前j个,A中划了k个子串,最后一个和现在这个i是否连续(挨着)
//无论何时 dp[i][j][k][0] = dp[i-1][j][k][0] + d[i-1][j][k][1];扔掉i之后前i-1和B前j划k个子串
//当 A_i == B_j 时
//  dp[i][j][k][1] = dp[i-1][j-1][k][1] + dp[i-1][j-1][k-1][0] + dp[i-1][j-1][k-1][1];
//    不看A[i],B[j](已经配对),只关注前面的来转移
//                    这个是连着前面            不连着前面              可以连着前面但是(由于划分不同也算不同所以可以)不连
//当 A_i != B_j 时
// dp[i][j][k][0] = 0;
//如果直接压维注意代码中的else