zoukankan      html  css  js  c++  java
  • [CF1149B] Three Religions

    Description

    给定长度为 (n) 的母串和三个子串 (s_1,s_2,s_3)。初始时子串均为空。

    (q) 次询问。你需要支持两种操作:向某个子串末尾添加一个字母,或者删去某个子串末尾的字母。

    在每次操作后,你需要回答,是否能从母串中分离出三个不相交的子序列,满足这三个子序列恰好是 (s_1,s_2,s_3)

    在任意时刻,(s_1,s_2,s_3) 的长度均不会超过 (250)

    (1 le n le 10^5) , (1le q le 10^3)

    Solution

    (f[i][j][k]) 表示三个子串分别匹配到了第 (i,j,k) 个字符,在母串中推进的最短距离

    (g[i][c]) 表示 (S[i..n]) 内字符 (c) 第一次出现的位置

    [f[i][j][k]=left{ egin{aligned} & g[f[i-1][j][k]+1][s_1[i]] \ & g[f[i][j-1][k]+1][s_2[j]] \ & g[f[i][j][k-1]+1][s_3[k]] end{aligned} ight. ]

    初始条件 (f[0][0][0]=0),其余初值设为 (+infty)

    对于插入操作,暴力计算即可,每次 (O(l^2))

    对于删除操作,减小串长即可

    对于询问,比较 (f[l_1][l_2][l_3]) 是否 (le n) 即可

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 100005;
    
    char s[N],s1[N],s2[N],s3[N];
    int n,l1,l2,l3,q,id,g[N][26],f[255][255][255];
    char op,tmp;
    
    void presolve()
    {
        for(int i=0;i<26;i++)
        {
            int ch='a'+i;
    
            vector <int> vec;
            for(int j=1;j<=n;j++) if(s[j]==ch) vec.push_back(j);
    
            int pos=1;
            for(auto now:vec)
            {
                for(int j=pos;j<=now;j++) g[j][i]=now;
                pos=now+1;
            }
            for(int j=pos;j<=n+2;j++) g[j][i]=n+1;
        }
    }
    
    void dp1(int i)
    {
        for(int j=0;j<=l2;j++)
        {
            for(int k=0;k<=l3;k++)
            {
                int tmp=1e9;
                if(i) tmp=min(tmp, g[f[i-1][j][k]+1][s1[i]-'a']);
                if(j) tmp=min(tmp, g[f[i][j-1][k]+1][s2[j]-'a']);
                if(k) tmp=min(tmp, g[f[i][j][k-1]+1][s3[k]-'a']);
                f[i][j][k]=tmp;
            }
        }
    }
    
    void dp2(int j)
    {
        for(int i=0;i<=l1;i++)
        {
            for(int k=0;k<=l3;k++)
            {
                int tmp=1e9;
                if(i) tmp=min(tmp, g[f[i-1][j][k]+1][s1[i]-'a']);
                if(j) tmp=min(tmp, g[f[i][j-1][k]+1][s2[j]-'a']);
                if(k) tmp=min(tmp, g[f[i][j][k-1]+1][s3[k]-'a']);
                f[i][j][k]=tmp;
            }
        }
    }
    
    void dp3(int k)
    {
        for(int i=0;i<=l1;i++)
        {
            for(int j=0;j<=l2;j++)
            {
                int tmp=1e9;
                if(i) tmp=min(tmp, g[f[i-1][j][k]+1][s1[i]-'a']);
                if(j) tmp=min(tmp, g[f[i][j-1][k]+1][s2[j]-'a']);
                if(k) tmp=min(tmp, g[f[i][j][k-1]+1][s3[k]-'a']);
                f[i][j][k]=tmp;
            }
        }
    }
    
    void cl1(int i)
    {
        for(int j=0;j<=l2;j++)
        {
            for(int k=0;k<=l3;k++)
            {
                f[i][j][k]=n+1;
            }
        }
    }
    
    void cl2(int j)
    {
        for(int i=0;i<=l1;i++)
        {
            for(int k=0;k<=l3;k++)
            {
                f[i][j][k]=n+1;
            }
        }
    }
    
    void cl3(int k)
    {
        for(int i=0;i<=l1;i++)
        {
            for(int j=0;j<=l2;j++)
            {
                f[i][j][k]=n+1;
            }
        }
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin>>n>>q>>s+1;
    
        for(int i=0;i<=254;i++)
        {
            for(int j=0;j<=254;j++)
            {
                for(int k=0;k<=254;k++)
                {
                    f[i][j][k]=n+1;
                }
            }
        }
    
        presolve();
    
        f[0][0][0]=0;
    
        for(int i=1;i<=q;i++)
        {
            cin>>op;
            if(op=='+')
            {
                cin>>id>>tmp;
                if(id==1) s1[++l1]=tmp, dp1(l1);
                if(id==2) s2[++l2]=tmp, dp2(l2);
                if(id==3) s3[++l3]=tmp, dp3(l3);
            }
            else
            {
                cin>>id;
                if(id==1) cl1(l1), --l1;
                if(id==2) cl2(l2), --l2;
                if(id==3) cl3(l3), --l3;
            }
            cout<<(f[l1][l2][l3]<=n ? "YES" : "NO")<<endl;
        }
    }
    
    
  • 相关阅读:
    广域网(ppp协议、HDLC协议)
    0120. Triangle (M)
    0589. N-ary Tree Preorder Traversal (E)
    0377. Combination Sum IV (M)
    1074. Number of Submatrices That Sum to Target (H)
    1209. Remove All Adjacent Duplicates in String II (M)
    0509. Fibonacci Number (E)
    0086. Partition List (M)
    0667. Beautiful Arrangement II (M)
    1302. Deepest Leaves Sum (M)
  • 原文地址:https://www.cnblogs.com/mollnn/p/13329716.html
Copyright © 2011-2022 走看看