E. Erase Subsequences dp
题:https://codeforces.com/contest/1303/problem/E
题意:给定一字符串s,问能否用最多俩次机会抽取出子序列组成目标字符串t
分析:先判断能否一次就构成目标t,否则我们枚举t,使其分为左右俩部分t1,t2,然后查询能否构成s,设dp[i][j]位s匹配到i位置,t1匹配到 j 位置,t2的最大匹配位置,转移注释
#include<bits/stdc++.h> using namespace std; const int M=404; int dp[M][M]; bool check(string s,string t1,string t2){ memset(dp,-1,sizeof(dp)); dp[0][0]=0; for(int i=0;i<s.size();i++) for(int j=0;j<=t1.size();j++) if(dp[i][j]>=0){ if(j<t1.size()&&s[i]==t1[j]){///t1匹配到了 dp[i+1][j+1]=max(dp[i+1][j+1],dp[i][j]); } if(dp[i][j]<t2.size()&&s[i]==t2[dp[i][j]]){///t2匹配到了,t1没动 dp[i+1][j]=max(dp[i+1][j],dp[i][j]+1); } ///都没匹配上 dp[i+1][j]=max(dp[i+1][j],dp[i][j]); } int res1=dp[s.size()][t1.size()]; int res2=t2.size(); if(res1>=res2){ return true; } return false; } int main(){ ios::sync_with_stdio(false); cin.tie(0); int t; cin>>t; while(t--){ string s,s2; cin>>s>>s2; int nowi=0; for(int i=0;i<s.size();i++){ if(nowi<s2.size()&&s[i]==s2[nowi]) nowi++; } if(nowi==s2.size()){ cout<<"YES"<<'\n'; continue; } //cout<<"!!"<<endl; int flag=0; for(int i=0;i<s2.size()-1;i++){ string t1="",t2=""; for(int j=0;j<=i;j++) t1+=s2[j]; for(int j=i+1;j<s2.size();j++) t2+=s2[j]; if(check(s,t1,t2)){ flag=1; break; } } if(flag) cout<<"YES"<<'\n'; else cout<<"NO"<<'\n'; } return 0; }