CF1303E

Erase Subsequences - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

我们首先可以把 T 拆成两部分 L和R,再考虑L和R是否能从S中获取

那么我们可以设置出一个比较套路的dp状态:dp[i][j][k] 表示 S 前i位,成功匹配了L的前 j 位,R的前 k 位的状态是否成立

这个dp状态还是很好转移的:

    for(int mid=1;mid<=n;mid++) // 把 T 分成 1~mid,mid+1~m
    {
        int L=mid,R=m-mid;
        for(int i=0;i<=n;i++)
            for(int j=0;j<=L;j++)
                for(int k=0;k<=R;k++)
                    dp[i][j][k]=0;
        dp[0][0][0]=1;
        for(int i=1;i<=n;i++)
            for(int j=0;j<=L;j++)
                for(int k=0;k<=R;k++)
                {
                    if(dp[i-1][j][k]==0) continue;
                    dp[i][j][k]=1;
                    if(a[i]==b[j+1]&&j<L) dp[i][j+1][k]=1;
                    if(a[i]==b[mid+k+1]&&k<R) dp[i][j][k+1]=1;    
                }
        if(dp[n][L][R])  
        {
            puts("YES");
            return;
        }
    } 
    puts("NO");

但是这个是 O(n^4)的复杂度,会TLE。

考虑优化dp状态。

显然 S 前i位,成功匹配了L的前 j 位的时候,此时一定是R的匹配位数越多越好。

所以我们再设置一个dp状态:dp[i][j]表示 S 前i位,成功匹配了L的前 j 位的时候,R最多能匹配几位。(这个dp状态跟 CF837D 凑10的状态十分相似)

(本题的难点还是在于dp状态的设置)

此时我们便可以优化 k 循环,以此优化时间复杂度变成 O(n^3)

Code:

// LUOGU_RID: 110736592
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pb push_back   
#define popb pop_back  
#define fi first
#define se second
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
const int N=410;
//const int M=;
//const int inf=(int)1e9;
//const ll INF=(ll)1e18;
int T,n,m;
int dp[N][N];
char a[N],b[N];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
void solve()
{
    scanf("%s%s",a+1,b+1);
    n=strlen(a+1);
    m=strlen(b+1);
    for(int mid=1;mid<=m;mid++)
    {
        int L=mid,R=m-mid;
        for(int i=0;i<=n;i++)
            for(int j=0;j<=L;j++)
                dp[i][j]=-1;
        dp[0][0]=0;
        for(int i=1;i<=n;i++)
            for(int j=0;j<=L;j++) //dp[i-1][j]的值已知 
            {
                if(dp[i-1][j]==-1) continue;
                dp[i][j]=max(dp[i][j],dp[i-1][j]);
                if(a[i]==b[j+1]&&j<L) dp[i][j+1]=max(dp[i][j+1],dp[i-1][j]);
                int Rpos=dp[i-1][j]+mid+1;
                if(a[i]==b[Rpos]&&Rpos<=m) dp[i][j]=max(dp[i][j],dp[i-1][j]+1);
            }
//        printf("%d\n",mid);
//        for(int i=1;i<=n;i++)
//            for(int j=0;j<=L;j++)
//                printf("%d %d %d\n",i,j,dp[i][j]); 
        if(dp[n][L]==R)
        {
            puts("YES");
            return;
        }
    }
    puts("NO");
}
int main()
{
//    freopen("","r",stdin);
//    freopen("","w",stdout);
//    ios::sync_with_stdio(0);
//    cin.tie(0);
    T=read();
    while(T--) solve();
    return 0;
}

 

posted @ 2023-05-23 21:35  QAQ啥也不会  阅读(6)  评论(0编辑  收藏  举报