luoguP2679 子串

luoguP2679 子串

个人感觉\(noip\)系列中挺好的一道DP题目.

题面有点难理解.

我们设\(f_{i,j,k,0/1}\)表示\(A\)串前\(i\)个字符,匹配\(B\)串前\(j\)个字符,正在用第\(k\)的子串,且第\(i\)个字符选或者不选的方案数

则有\(f_{i,j,k,0} = f_{i - 1,j,k,0} + f_{i - 1,j,k,1}\)

如果\(A_i == A_j\),那么有

\(f_{i,j,k,1} = f_{i - 1,j - 1,k - 1,1} + f_{i - 1,j - 1,k - 1,0}+f_{i - 1,j - 1,k,1}\)

否则

\(f_{i,j,k,1} = 0\)(因为无法匹配)

但是,空间复杂度不够优秀。

将第一维滚掉就好了

#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1e3 + 3;
const int M = 2e2 + 2;
const int mod = 1e9 + 7;
int f[2][M][M][2];
int n,m,kk;
char s1[N],s2[M];
int main(){
	scanf("%d%d%d",&n,&m,&kk);
	scanf("%s%s",s1 + 1,s2 + 1);
	int now = 0;
	f[1][0][0][0] = f[0][0][0][0] = 1;
	for(int i = 1;i <= n;++i){
		for(int j = 1;j <= m;++j)
			for(int k = 1;k <= kk;++k){
				f[now][j][k][0] = (1ll * f[now ^ 1][j][k][0] + f[now ^ 1][j][k][1]) % mod;
				if(s1[i] == s2[j])
				f[now][j][k][1] = (1ll * f[now ^ 1][j - 1][k][1] 
				+ f[now ^ 1][j - 1][k - 1][0] + f[now ^ 1][j - 1][k - 1][1]) % mod;
				else f[now][j][k][1] = 0;			
		}
		now ^= 1;
	}
	printf("%d\n",(f[now ^ 1][m][kk][0] + f[now ^ 1][m][kk][1]) % mod);	
	return 0;	
}
posted @ 2019-05-03 18:31  wyxdrqcccc  阅读(122)  评论(0编辑  收藏  举报