P2679 NOIP2015T5 子串 DP+滚动数组

题意:给出两个字符串,求用第一个字符串中的子串去匹配第二个子串,而且第一个字符串的子串在匹配第二个字符串时要按顺序;

用滚动数组来优化DP,否则会MLE;

f[i][j][k][0/1]f[i][j][k][0/1]f[i][j][k][0/1]表示是否一定使用了 A串中的第 i个字符,并用了 A中的 k个子串来匹配了 B串中的前 j个字符 ( 0表示一定不用, 1表示一定用 )

状态转移方程:

f[i][j][k][0]=f[i−1][j][k][0]+f[i−1][j][k][1]f[i][j][k][0]=f[i-1][j][k][0]+f[i-1][j][k][1]f[i][j][k][0]=f[i1][j][k][0]+f[i1][j][k][1]

if(a[i]==b[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]=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]=f[i1][j1][k1][1]+f[i1][j1][k1][0]+f[i1][j1][k][1]

 

附上代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int mod = 1000000007;
const int N = 1011;

int n,m,sum;
int f[2][N][N][2];
char a[N],b[N];

int main()
{
	scanf("%d%d%d",&n,&m,&sum);
	scanf("%s%s",a+1,b+1);
	f[0][0][0][0]=1;//初始化 
	for(int i=1;i<=n;i++){
		int op=i&1;
		f[op][0][0][0]=1;//初始化 
		for(int j=1;j<=min(i,m);j++)
		for(int k=1;k<=min(j,sum);k++){
			f[op][j][k][0]=f[op][j][k][1]=0;//滚动数组覆盖 
			f[op][j][k][0]=(f[op^1][j][k][0]+f[op^1][j][k][1])%mod;
			if(a[i]==b[j]){
				f[op][j][k][1]=((f[op^1][j-1][k-1][1]+f[op^1][j-1][k-1][0])%mod+f[op^1][j-1][k][1])%mod;
			}
		}
	}
	printf("%d",(f[n&1][m][sum][1]+f[n&1][m][sum][0])%mod);
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/nnezgy/p/11366372.html