!-- Loading 底层遮罩 -->

P2679 子串

传送门

思路

定义状态 f(i,j,k)为以A的第 i 个字符为结尾取出 k 段后在字符串B匹配到 j 的方案数。则可知当A[i] != B[ j]时,该状态方案数为0 ,当A[i]==B[ j]时,A[ i ] 可以选择重启一段或者跟在上一段后面。情况2为 f(i-1,j-1,k),情况1是所有 f(x,j-1,k-1)之和,这里的x为 i 的任意一个前驱。利用前缀和优化所有前驱求和,滚动数组优化空间(k状态只和k-1状态有关)。

代码

#include<iostream>
#include<cstring>
#define MAXN 1007
#define mod 1000000007
using namespace std;
int n, m, k, dp[2][MAXN][MAXN], sum[2][MAXN][MAXN];
char A[MAXN], B[MAXN];
int main(void)
{
    cin >> n >> m >> k;
    cin >> &A[1] >> &B[1];
    for (int i = 0; i <= n; i++)
        sum[1][i][0] = 1;
    int cr = 0;
    for (int K = 1; K <= k; K++, cr ^= 1)
    {
        memset(dp[cr], 0, sizeof(dp[cr]));
        memset(sum[cr], 0, sizeof(sum[cr]));
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= m; j++)
            {
                if (A[i] == B[j])
                    dp[cr][i][j] = (dp[cr][i - 1][j - 1] + sum[cr ^ 1][i - 1][j - 1]) % mod;
                sum[cr][i][j] = (sum[cr][i - 1][j] + dp[cr][i][j]) % mod;
            }
        }
    }
    cout << sum[cr ^ 1][n][m];
    return 0;
}
 

 

posted @ 2022-03-30 20:12  Thinker-X  阅读(23)  评论(0)    收藏  举报