• Codeforces 1050D Three Religions (dp+序列自动机)


    题意:

    给一个1e5的串str,然后有三个起始空串,不超过1000次操作,对三个字符串的一个尾部加一个字符或者减一个字符,保证每个字符不会超过250

    每次操作之后询问你这三个串是不是可以组成str的子序列,

    比如ab,cd,ef可以组成acgbdef的子序列

    思路:

    dp[i][j][k]为三个串分别匹配到i,j,k的时候组成的子序列的最后一个字符在str中的位置,如果dp[strlen(str1)][strlen(str2)][strlen(str3)]>n则输出no

    对每一次询问我们可以处理出dp[i][j][k],

    用序列自动机加速,nx[i][j]表示str中i位置的下一个字符j出现在什么位置(不包括i),没出现则为n+1

    则状态转移方程

    if(i)dp[i][j][k] = min(dp[i][j][k],nx[dp[i-1][j][k]][v[1][i-1]-'a']);
    if(j)dp[i][j][k] = min(dp[i][j][k],nx[dp[i][j-1][k]][v[2][j-1]-'a']);
    if(k)dp[i][j][k] = min(dp[i][j][k],nx[dp[i][j][k-1]][v[3][k-1]-'a']);

    注意序列自动机要同样处理处nx[0][j]和nx[n+1][j],因为状态转移方程中可能会出现

    复杂度O(250^3)

    但这一题有q次询问,而且三个串在不停改变,我们不能每次都250^3处理,

    当操作为“+”的时候,如果添加的是str1,若str1的长度由m变为m+1,可以发现,dp方程改变的只有dp[m+1][j][k],而其他的都没有改变(因为只是在尾部操作)

    所以我们对每一次询问可以O(250^2)更新dp数组

    而当操作为"-"的时候,我们并不需要更新dp数组,因为我们只能用到dp[m-1][j][k],而这之前已经处理好了,我们下一次“+”的时候,自然会覆盖dp[m][j][k]

    所以总的复杂度为$O(26n+250^2q)$

    代码:

    题解的写法学会了✔

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
    #include<functional>
        
    #define fst first
    #define sc second
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lc root<<1
    #define rc root<<1|1
    #define lowbit(x) ((x)&(-x)) 
    
    using namespace std;
    
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef long long LL;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
    
    const db eps = 1e-6;
    const int mod = 1e9+7;
    const int maxn = 1e6+100;
    const int maxm = 2e6+100;
    const int inf = 0x3f3f3f3f;
    const db pi = acos(-1.0);
    
    
    int n, q;
    int dp[333][333][333];
    vector<char>v[4];
    int nx[maxn][26];
    char str[maxn];
    void init(){
        for(int i = 0; i < 26; i++){
            nx[n][i] = n+1;
            nx[n+1][i]=n+1;
        }
        for(int i = n-1; i >= 0; i--){
            for(int j = 0; j < 26; j++){
                if(str[i+1]-'a'==j){
                    nx[i][j] = i+1;
                }
                else nx[i][j] = nx[i+1][j];
            }
        }
    }int mi[4],mx[4];
    int main(){
        scanf("%d %d" ,&n, &q);
        scanf("%s",str+1);
        init();
        while(q--){
            char op[3];
            scanf("%s",op+1);
            int x;
            scanf("%d",&x);
            if(op[1]=='+'){
                char gao[3];
                scanf("%s",gao+1);
                char c = gao[1];
                v[x].pb(c);
                
                for(int i = 1; i <= 3; i++){
                    mi[i] = 0;
                    mx[i] = v[i].size();
                }
                mi[x] = mx[x];
                for(int i = mi[1]; i <= mx[1]; i++){
                    for(int j = mi[2]; j <= mx[2]; j++){
                        for(int k = mi[3]; k <= mx[3]; k++){
                            if(i+j+k==0)continue;
                            dp[i][j][k] = n+1;
                            if(i)dp[i][j][k] = min(dp[i][j][k],nx[dp[i-1][j][k]][v[1][i-1]-'a']);
                            if(j)dp[i][j][k] = min(dp[i][j][k],nx[dp[i][j-1][k]][v[2][j-1]-'a']);
                            if(k)dp[i][j][k] = min(dp[i][j][k],nx[dp[i][j][k-1]][v[3][k-1]-'a']);
                        }
                    }
                }
                
            }
            else{
                
                v[x].pop_back();
            }
            if(dp[v[1].size()][v[2].size()][v[3].size()]<=n){
                printf("YES
    ");
            }
            else printf("NO
    ");
        }
        return 0;
    }
    /*
     */
  • 相关阅读:
    shell流程控制
    shell编程变量介绍与表达式详解
    shell编程简介
    反向代理与负载均衡
    存储库之mongodb,redis,mysql
    请求库之requests,selenium
    解析库之re、beautifulsoup、pyquery
    爬虫基本原理
    Django 函数和方法的区别
    Django 知识补漏单例模式
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/10799952.html
Copyright © 2020-2023  润新知