codeforces1303E. Erase Subsequences(dp)
题意:
给出两个字符串 s s s, p p p ,有一种操作:
取 s s s 中的某一个子序列 t t t ,将其加入到 p ′ p' p′的末尾 ,并在原串中删除。
最多只能进行两次操作,问 p ′ p' p′ 能否等于 p p p
题解:
枚举字符串 p p p 的断点,前一部分的长度为 l e n 1 len1 len1 ,后一部分的长度为 l e n 2 len2 len2 。
设 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示原串 s s s 匹配前半部分的 i i i个字符,后半部分的 j j j 个字符,最少需要的长度。
那么只需判断 d p [ l e n 1 ] [ l e n 2 ] ≤ n dp[len1][len2] \leq n dp[len1][len2]≤n即可。
对于转移,有两个, d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] dp[i-1][j],dp[i][j-1] dp[i−1][j],dp[i][j−1] ,那么先预处理出每个后缀的每个字母最近的位置,然后看 p i / p j p_i/p_j pi/pj最近在哪即可。
代码:
#pragma GCC diagnostic error "-std=c++11"
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int MAXN=5e2+5;
const int inf=0x3f3f3f3f;
int nex[MAXN][30];
char s[MAXN];
int dp[MAXN][MAXN];
char st[MAXN];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin >> s + 1;
        cin >> st + 1;
        int n = strlen(s + 1);
        int m = strlen(st + 1);
        for (int i = 1; i <= 26;i++)
            nex[n+1][i] = n + 1;
        for (int i = n; i >= 1;i--)
        {
            for (int j = 1; j <= 26;j++){
                nex[i][j] = nex[i + 1][j];
            }
            nex[i][s[i] - 'a' + 1] = i;
        }
        //cout << nex[1][1] << endl;
        int flag = 0;
        for (int i = 0; i <= m;i++)
        {
            int len1 = i, len2 = m - i;
            dp[0][0] = 0;
            for (int j = 0; j <= len1;j++)
            {
                for (int k = 0; k <= len2;k++)
                {
                    if(!j&&!k)
                        continue;
                    int pos1 = j, pos2 = i + k;
                    dp[j][k] = n + 1;
                    if(j-1>=0&&dp[j-1][k]<=n)
                    {
                        dp[j][k] = min(dp[j][k],nex[dp[j - 1][k] + 1][st[pos1] - 'a' + 1]);
                    }
                    if(k-1>=0&&dp[j][k-1]<=n)
                    {
                        dp[j][k] = min(dp[j][k], nex[dp[j][k-1] + 1][st[pos2] - 'a' + 1]);
                    }
                }
            }
            if(dp[len1][len2]<=n) {
                //cout << i << endl;
                flag = 1;
                break;
            }
        }
        if(flag)
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
}

 
                
             
         浙公网安备 33010602011771号
浙公网安备 33010602011771号