• 【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。

    P.S:贪心策略好像有bug。。。大家还是写后缀数组吧。

    #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
    ");
    				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
    ");
    		return ;
    	}
    	printf("NO
    ");
    }
    int main()
    {
    	scanf("%d",&T);
    	while(T--)	work();
    	return 0;
    }//1 9 6 3 hloyaygrt loyyrt
  • 相关阅读:
    boost库:函数对象
    boost库:智能指针
    linux 查看和修改文件时间
    linux正则表达式
    UVA
    UVA
    UVA
    UVA
    UVA
    对JavaScript的认识?
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7750126.html
Copyright © 2020-2023  润新知