🙏 🙏 🙏
分为两部分,先检查抽一次是否可以,再枚举第一次抽到哪,检查是否可行,昨天没想出来怎么搞第二部分,今天看了看是DP,,,
dp[ i ] [ j ] 表示s该用第i个,并且t1该匹配到了第j个时,t2最多该匹配哪个,注意状态转移时要从合法状态转移(dp小于0时不操作)
//1,检查用一次是否能够
//2,枚举t分成两段的交点
bool check (const string & s,const string & t)
{
int r=0;
if(r==t.size()) return true;
for(char c:s)
{
if(c==t[r]) ++r;
if(r==t.size()) return true;
}
return false;
}
//dp[i][j] 表示s该用第i个,并且t1该匹配到了第j个时,t2最多该匹配哪个
bool can(const string & s,const string& t1,const string & t2)
{
int dp[444][444];
memset(dp,-1,sizeof(dp));
dp[0][0]=0;
for(int i=0;i<sz(s);++i)
{
for(int j=0;j<=sz(t1);++j)
{
if(dp[i][j]<0) continue;
if(j<sz(t1)&&s[i]==t1[j])//用来匹配t1
dp[i+1][j+1]=max(dp[i+1][j+1],dp[i][j]);
if(dp[i][j]<sz(t2)&&s[i]==t2[dp[i][j]])//用来匹配t2
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]);//谁也不匹配
}
}
if(dp[sz(s)][sz(t1)]>=sz(t2)) return true;
return false;
}
bool solve()
{
string s,t;cin>>s>>t;
if(check(s,t)) return true;
for(int i=0;i<t.size()-1;++i)//枚举第一段的末尾
{
string t1="",t2="";
for(int j=0;j<=i;++j) t1+=t[j];
for(int j=i+1;j<sz(t);++j) t2+=t[j];
if(can(s,t1,t2)) return true;
}
return false;
}
signed main()
{
int T;cin>>T;
while(T--)
{
if(solve()) cout<<"YES\n";
else cout<<"NO\n";
}
return 0;
}