码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-04-30 15:29:33      阅读:98      评论:0      收藏:0      [点我收藏+]

标签:else   can   跳表   char   --   amp   while   就是   fine   

题目设计的很好,感觉做了这题对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]<<‘\n‘;
                    }
            }
            
            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]<<‘\n‘;
        if(dp[A][B][C]!=n+1)puts("YES");
        else puts("NO");
    }
} 

 

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

标签:else   can   跳表   char   --   amp   while   就是   fine   

原文地址:https://www.cnblogs.com/zsben991126/p/10796149.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!