BZOJ5073[Lydsy十月月赛]小A的咒语 DP

Posted CQzhangyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ5073[Lydsy十月月赛]小A的咒语 DP相关的知识,希望对你有一定的参考价值。

【BZOJ5073】[Lydsy十月月赛]小A的咒语

题解:沙茶DP,完全不用后缀数组。

用f[i][j]表示用了A的前i个字符,用了j段,最远能匹配到哪。因为显然我们能匹配到的地方越远越好,所以我们直接判断A[i]和B[f[i][j]]是否相等,如果相等则转移下去。还要记录g[i][j]表示第i个字符匹配成功时最远能匹配到哪,这样f数组可以求前缀最大值,但要从j转移到j+1,而g数组可以从j转移到j。

 

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=100010;
int n,m,K,T,ans;
char s1[maxn],s2[maxn];
int f[maxn][110],g[maxn][110];
void work()
{
	scanf("%d%d%d%s%s",&n,&m,&K,s1,s2),ans=0;
	int i,j;
	memset(f,0,sizeof(f)),memset(g,0xc0,sizeof(g));
	for(i=0;i<n;i++)
	{
		for(j=0;j<=K;j++)
		{
			if(f[i][j]==m||g[i][j]==m)
			{
				printf("YES\n");
				return ;
			}
			f[i][j]=max(f[i][j],g[i][j]);
			if(s1[i]==s2[f[i][j]])	g[i+1][j+1]=max(g[i+1][j+1],f[i][j]+1);
			if(g[i][j]>=0&&s1[i]==s2[g[i][j]])	f[i+1][j+1]=max(f[i+1][j+1],g[i][j]+1),g[i+1][j]=max(g[i+1][j],g[i][j]+1);
			f[i+1][j]=max(f[i+1][j],f[i][j]);
		}
	}
	for(j=0;j<=K;j++)	if(f[n][j]==m||g[n][j]==m)
	{
		printf("YES\n");
		return ;
	}
	printf("NO\n");
}
int main()
{
	scanf("%d",&T);
	while(T--)	work();
	return 0;
}//1 9 6 3 hloyaygrt loyyrt

 

以上是关于BZOJ5073[Lydsy十月月赛]小A的咒语 DP的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ5072[Lydsy十月月赛]小A的树 树形DP

BZOJ5074[Lydsy十月月赛]小B的数字 数学

bzoj5074[Lydsy十月月赛]小B的数字 数学

bzoj5072[Lydsy十月月赛]小A的树 树形背包dp

bzoj 5072 [Lydsy1710月赛]小A的树——树形dp

bzoj 5091: [Lydsy0711月赛]摘苹果