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;
}
View Code

猜你喜欢

转载自www.cnblogs.com/starve/p/12383074.html