[LUOGU] P2679 子串

一开始用一个f数组转移,发现不太对,状态有重叠部分

f[i][j][k]表示考虑了s的前i位,匹配到t的第j位,用了k个子串,且s的第i位必选

g[i][j][k]表示考虑了s的前i位,匹配到t的第j位,用了k个子串,且s的第i位必不选


考虑i的前一位:前一位选(作为结尾),前一位选(不作为结尾),前一位不选

f[i][j][k]=f[i-1][j-1][k]+f[i-1][j-1][k-1]+g[i-1][j-1][k-1]

第i位不选时继承状态

g[i][j][k]=g[i-1][j][k]+f[i-1][j][k]

滚动数组省一维

#include<iostream>
#include<cstring>
#include<cstdio>
#define int long long
using namespace std;

inline int rd(){
    int ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    while(isdigit(c))ret=ret*10+c-'0',c=getchar();
    return ret*f;
}

const int MAXN=1007;
const int MOD=1000000007;
int n,m,num;

char s[MAXN],t[MAXN];
int f[2][MAXN][MAXN],g[2][MAXN][MAXN]; 

signed main(){
    n=rd();m=rd();num=rd();
    scanf("%s%s",s+1,t+1);
    s[0]='a';t[0]='b';
    g[0][0][0]=1;
    for(int i=1;i<=n;i++){
        g[i&1][0][0]=1;
        for(int j=1;j<=m&&j<=i;j++){
            for(int k=1;k<=num;k++){
                f[i&1][j][k]=g[i&1][j][k]=0;
                g[i&1][j][k]=(g[(i-1)&1][j][k]+f[(i-1)&1][j][k])%MOD;
                if(s[i]==t[j]){
                    f[i&1][j][k]=(f[(i-1)&1][j-1][k-1]+f[(i-1)&1][j-1][k]+g[(i-1)&1][j-1][k-1])%MOD;
                }else{
                    f[i&1][j][k]=0;
                }
            }
        }
    }
    cout<<(f[n&1][m][num]+g[n&1][m][num])%MOD;
    return 0;
}

本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9399772.html

原文地址:https://www.cnblogs.com/ghostcai/p/9399772.html