Description
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;
}