【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\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
| 欢迎来原网站坐坐! >原文链接<