1 条题解

  • 0
    @ 2025-8-24 21:40:23

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar frankchenfu
    **

    搬运于2025-08-24 21:40:22,当前版本为作者最后更新于2018-02-22 21:38:35,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    看到各位DP数组都只开两三维的我很害怕啊,我来讲一讲如何很暴力的做这道题。


    状态

    首先我们考虑设计状态。我们发现,为了保证无后效性的一位一位往后推,我们需要记录当前推到aa串的哪一个位置了;接着还有记录匹配了bb串的那几个字符。因为是按照原串顺序,所以相当于是即匹配bb的前几个字符。有这些还不够,我们还要记录划分了几个子串。最后,为了便于转移,我们还要标记一维0/1状态,表示aa串中的第ii个字符是否选入。

    这样,我们就设计好了状态。我们记fi,j,p,vf_{i,j,p,v}表示到aa串的第ii个位置为止使用pp个子串匹配bb串前jj位字符且第ii个位置选或不选(vv)的方案数。


    转移

    设计好状态,不会转移怎么行。我们分情况考虑。

    1. ai=bja_i=b_j时:

      1. fi,j,p,0f_{i,j,p,0}:由于这位不选,所以就是前面一位选和不选方案数之和,即fi,j,p,0=fi1,j,p,0+fi1,j,p,1f_{i,j,p,0}=f_{i-1,j,p,0}+f_{i-1,j,p,1}

      2. 容易得到$f_{i,j,p,1}=f_{i-1,j-1,p,1}+f_{i-1,j-1,p-1,0}+f_{i-1,j-1,p-1,1}$.

    2. aibja_i\ne b_j时:

      1. 不选情况同上,即fi,j,p,0=fi1,j,p,0+fi1,j,p,1f_{i,j,p,0}=f_{i-1,j,p,0}+f_{i-1,j,p,1}.

      2. 由于选不了,自然就是00,即fi,j,p,1=0f_{i,j,p,1}=0.


    优化空间

    如果你读完状态设计之后又稍微思考就会发现,空间可能较大。空间不够怎么办?在luogu还好说,如果真的在NOIP,应该是不敢开1000×200×200×2=8×1071000\times200\times200\times2=8\times10^7的数组吧。所以我们观察转移方程,发现每次转移只用到了前一位!于是我们把第一维很愉快地滚掉了。这样,空间复杂度就保证是O(mk)O(mk)了。那么时间呢?时间是O(nmk)O(n\cdot mk),但是时间不像空间,这个复杂度是可以接受的。于是,完整算法就结束了。


    Cpp代码:

    #include<cstdio>
    #include<cstring>
    const int MAXN=1010;
    const int MAXM=210;
    const int MOD=(int)(1e9)+7;
    int f[2][MAXM][MAXM][2];
    char a[MAXN],b[MAXM];
    int n,m,k;bool val=1;
    
    void dp(){
        f[0][0][0][0]=f[1][0][0][0]=1;
        for(int i=1;i<=n;i++,val^=1)
            for(int j=1;j<=m;j++)
                for(int p=1;p<=k;p++){
                    if(a[i]==b[j]){
                        f[val][j][p][0]=(f[val^1][j][p][0]+f[val^1][j][p][1])%MOD;
                        f[val][j][p][1]=(f[val^1][j-1][p][1]+\
                                        (f[val^1][j-1][p-1][0]+f[val^1][j-1][p-1][1])%MOD)%MOD;
                    }
                    else{
                        f[val][j][p][0]=(f[val^1][j][p][0]+f[val^1][j][p][1])%MOD;
                        f[val][j][p][1]=0;
                    }
                }
    }
    
    int main(){
        scanf("%d%d%d",&n,&m,&k);
        scanf("%s%s",a+1,b+1);
        dp();
        printf("%d\n",(f[n&1][m][k][0]+f[n&1][m][k][1])%MOD);
        return 0;
    }
    
    • 1

    信息

    ID
    1723
    时间
    1000ms
    内存
    125MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者