洛谷 2679 子串

题面

题解

比较简单的线性dp,dp[i][j][k][1]表示A串前i个,B串前j个,一共匹配了j组,这个字符是否匹配的
方案数,转移方程比较好想,但是这道题要用滚动数组(因为没清零调了半天),深刻认识到了
滚动数组的用法,注意两个连着的匹配也可以算作两组。

代码

#include<bits/stdc++.h>

using namespace std;
const int MAXN = 1005;
const int MAXM = 205;
const int mod = 1e9+7; 

int n,m,K;
int dp[2][MAXM][MAXM][2];
char ch[MAXN],c[MAXM];
int ans;

int main(){
    scanf("%d%d%d",&n,&m,&K);
    scanf("%s",ch+1);
    scanf("%s",c+1);
    dp[0][0][0][0]=1;
    dp[1][0][0][0]=1;   //!!!
    for(register int i=1;i<=n;i++)
        for(register int j=1;j<=min(i,m);j++){
            for(register int k=1;k<=min(i,K);k++){
                dp[i&1][j][k][0]=dp[i&1][j][k][1]=0;    //超级重要!!!
                dp[i&1][j][k][0]+=dp[(i-1)&1][j][k][0];
                dp[i&1][j][k][0]%=mod;
                dp[i&1][j][k][0]+=dp[(i-1)&1][j][k][1];
                dp[i&1][j][k][0]%=mod;
                if(ch[i]==c[j]){
                    dp[i&1][j][k][1]+=dp[(i-1)&1][j-1][k-1][0];
                    dp[i&1][j][k][1]%=mod;
                    dp[(i&1)][j][k][1]+=dp[(i-1)&1][j-1][k][1];
                    dp[i&1][j][k][1]%=mod;
                    dp[i&1][j][k][1]+=dp[(i-1)&1][j-1][k-1][1];
                    dp[i&1][j][k][1]%=mod;
                }
//              cout<<dp[i&1][j][k][0]<<" "<<dp[i&1][j][k][1]<<endl;
            }
        }
    ans=dp[n&1][m][K][0]+dp[n&1][m][K][1];
    ans%=mod;
    printf("%d",ans);
    return 0;
}
posted @ 2018-06-19 09:52  Monster_Qi  阅读(81)  评论(0编辑  收藏  举报