P2679 NOIP2015子串

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2679 NOIP2015子串相关的知识,希望对你有一定的参考价值。

技术分享

 

很自然想到DP

这道题使我意识到自己的DP功力还有很大不足

用f[i][j][k][0/1]表示A串到i位,B串到j位,A串分为了k部分,第i位是否匹配进B串的方案数(一般套路)

优化:滚动数组,设置pre,now,

教训:

  1、别图省事,把该写全的写全

  2、找个好弄一点的DP边界

  3、一个方程不大好转移就换一个,

  4、经常从i-1或j-1转移过来

  5、看数据范围猜循环

看到DP题时:

想状态,想转移,想边界,想决策();

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 1009
#define M 209
#define mod 1000000007
using namespace std;
int n,m,KK;
char s[N];
int a[N],b[M];

int f[2][M][M][2];
int cnt;

int pre,now;

int main(){
	cin>>n>>m>>KK;
	scanf("%s",s);
	for(int i=1;i<=n;++i)a[i]=s[i-1];
	scanf("%s",s);
	for(int i=1;i<=m;++i)b[i]=s[i-1];
	
	
	pre=0;now=1;
	for(int i=1;i<=n;++i){
		f[now][1][1][0]=cnt;
		if(a[i]==b[1]){
			f[now][1][1][1]=1;
			++cnt;
		}else{
			f[now][1][1][1]=0;
		}
		for(int j=2;j<=m;++j){
			for(int k=1;k<=KK;++k){
				f[now][j][k][0]=(f[pre][j][k][0]+f[pre][j][k][1])%mod;
				if(a[i]==b[j])f[now][j][k][1]=(f[pre][j-1][k-1][1]+f[pre][j-1][k-1][0]+(long long)f[pre][j-1][k][1])%mod;
				else f[now][j][k][1]=0;
			}
		}
		//memset(f[pre],0,sizeof(f[pre])); 
		swap(pre,now);
	}
	
	printf("%d\\n",(f[pre][m][KK][0]+f[pre][m][KK][1])%mod);
	return 0;
}

  

以上是关于P2679 NOIP2015子串的主要内容,如果未能解决你的问题,请参考以下文章

[NOIP2015提高组]子串

P2679 子串

P2679 子串

P2679 子串

P2679 子串

洛古 P2679 子串 题解