• 跳表上线性dp——1150D 好题!


    题目设计的很好,感觉做了这题对dp的状态有了更深的理解

    /*
    先预处理序列自动机 
    dp[i][j][k]表示匹配到i,j,k时的最靠前的位置
    那么现在A串加入了一个字母,我们要求的就是dp[i+1][j][k]
    根据dp的状态转移    
        因为 dp[i][j][k]之前的状态已经全部确定下来,
        所以只要在i+1的状态下枚举两重循环jk即可 
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 100005
    char s[maxn];
    int n,pos[26],q,nxt[maxn][26];
    void init(){
        for(int i=0;i<26;i++)pos[i]=n+1;
        for(int i=n;i>=0;i--){
            for(int j=0;j<26;j++)
                nxt[i][j]=pos[j];
            pos[s[i]-'a']=i;
        }
        for(int i=0;i<26;i++)
            nxt[n+1][i]=n+1;
    }
    
    int A,B,C,dp[300][300][300];
    char a[maxn],b[maxn],c[maxn];
    int main(){
        scanf("%d%d%s",&n,&q,s+1);
        init();
        char op[2],ch[2];int p;
        while(q--){
            cin>>op>>p;
            if(op[0]=='-'){
                if(p==1)A--;if(p==2)B--;if(p==3)C--;
            }
            else {
                cin>>ch;
                if(p==1){//带A的所有新状态 
                    a[++A]=ch[0];
                    for(int j=0;j<=B;j++)
                        for(int k=0;k<=C;k++)
                            dp[A][j][k]=n+1;
                    for(int j=0;j<=B;j++)
                        for(int k=0;k<=C;k++){
                            dp[A][j][k]=min(dp[A][j][k],nxt[dp[A-1][j][k]][a[A]-'a']);
                            if(j)dp[A][j][k]=min(dp[A][j][k],nxt[dp[A][j-1][k]][b[j]-'a']);
                            if(k)dp[A][j][k]=min(dp[A][j][k],nxt[dp[A][j][k-1]][c[k]-'a']);    
                        //cout<<dp[A][j][k]<<'
    ';
                        }
                }
                
                if(p==2){
                    b[++B]=ch[0];
                    for(int i=0;i<=A;i++)
                        for(int k=0;k<=C;k++)
                            dp[i][B][k]=n+1;
                    for(int i=0;i<=A;i++)
                        for(int k=0;k<=C;k++){
                            dp[i][B][k]=min(dp[i][B][k],nxt[dp[i][B-1][k]][b[B]-'a']);
                            if(i)dp[i][B][k]=min(dp[i][B][k],nxt[dp[i-1][B][k]][a[i]-'a']);
                            if(k)dp[i][B][k]=min(dp[i][B][k],nxt[dp[i][B][k-1]][c[k]-'a']);
                        }    
                }
                
                if(p==3){
                    c[++C]=ch[0];
                    for(int i=0;i<=A;i++)
                        for(int j=0;j<=B;j++)
                            dp[i][j][C]=n+1;
                    for(int i=0;i<=A;i++)
                        for(int j=0;j<=B;j++){
                            dp[i][j][C]=min(dp[i][j][C],nxt[dp[i][j][C-1]][c[C]-'a']);
                            if(i)dp[i][j][C]=min(dp[i][j][C],nxt[dp[i-1][j][C]][a[i]-'a']);
                            if(j)dp[i][j][C]=min(dp[i][j][C],nxt[dp[i][j-1][C]][b[j]-'a']);    
                        }
                }
            }
        //    cout<<dp[A][B][C]<<'
    ';
            if(dp[A][B][C]!=n+1)puts("YES");
            else puts("NO");
        }
    } 
  • 相关阅读:
    JAVA中的SimpleDateFormat yyyy和YYYY的区别
    Mysql的MVCC
    SELECT语句中的for update的用法(锁的运用)
    今天简单说一下cdc 的使用
    sqlserver cdc用法
    JAVA | Java对象的内存分配过程是如何保证线程安全的?
    物联网(莹石云)WIFI一键配置原理分析(zz)
    Dell xps 13 9350待机时总是关机的处理方法
    Vue系列:在vux的popup组件中使用百度地图遇到显示不全的问题
    如何通过百度地图将经纬度转换为地址信息
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10796149.html
Copyright © 2020-2023  润新知