jzoj5220 [GDOI2018模拟7.10]C dp

Description


这里写图片描述
n 1000

Solution


先n^2做一次最长公共子序列,考虑怎么求方案
我们对求出的f数组再做一次dp。设g[i,j]为X的前i个和Y的前j个,最长公共子序列长度为f[i,j]的方案数
若i不匹配,则g[i,j]+=g[i-1][j]
若i匹配,我们从后往前找到第一个X[i]=Y[j]的位置k,g[i,j]+=g[i-1,k-1]。这个东西可以预处理

感觉去年的题有点水啊

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)

const int MOD=1000000007;
const int N=1005;

char a[N],b[N];

int f[N][N],g[N][N];
int pre[N][26];

int main(void) {
    scanf("%s",a+1); scanf("%s",b+1);
    int n=strlen(a+1),m=strlen(b+1);
    rep(i,1,m) {
        rep(j,0,25) pre[i][j]=pre[i-1][j];
        pre[i][b[i]-'a']=i;
    }
    int ans=0,prt;// g[0][0]=1;
    rep(i,1,n) rep(j,1,m) {
        f[i][j]=std:: max(f[i-1][j],f[i][j-1]);
        if (a[i]==b[j]) f[i][j]=std:: max(f[i][j],f[i-1][j-1]+1);
    }
    rep(i,0,n) g[i][0]=1;
    rep(i,0,m) g[0][i]=1;
    rep(i,1,n) rep(j,1,m) {
        if (f[i-1][j]==f[i][j]) (g[i][j]+=g[i-1][j])%=MOD;
        int k=pre[j][a[i]-'a']; if (!k) continue;
        if (f[i-1][k-1]+1==f[i][j]) {
            (g[i][j]+=g[i-1][k-1])%=MOD;
        }
    }
    printf("%d\n", g[n][m]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/81132087
今日推荐