题解 P2679 【子串】
frankchenfu · · 题解
看到各位DP数组都只开两三维的我很害怕啊,我来讲一讲如何很暴力的做这道题。
状态
首先我们考虑设计状态。我们发现,为了保证无后效性的一位一位往后推,我们需要记录当前推到0/1状态,表示
这样,我们就设计好了状态。我们记
转移
设计好状态,不会转移怎么行。我们分情况考虑。
-
当
a_i=b_j 时:-
-
容易得到
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} .
-
-
当
a_i\ne b_j 时:-
不选情况同上,即
f_{i,j,p,0}=f_{i-1,j,p,0}+f_{i-1,j,p,1} . -
由于选不了,自然就是
0 ,即f_{i,j,p,1}=0 .
-
优化空间
如果你读完状态设计之后又稍微思考就会发现,空间可能较大。空间不够怎么办?在luogu还好说,如果真的在NOIP,应该是不敢开
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;
}