zoukankan      html  css  js  c++  java
  • Codeforces Round #501 (Div. 3) F: Bracket Substring

    一开始根本没想去重的事(T▽T)写了个辣鸡,然后样例纷纷苟住了。

    当时感到非常自豪.....

    dp[len][prefix][pos][0/1]: 前len位,左括号比右括号多prefix,与串s匹配到了第pos个位置,在len-1之前有没有完全匹配串s的方案数。

    关于状态转移,如果匹配上了,pos转移到pos+1,如果没匹配上,那就施展Fail指针。

    不过这么做很沙比的啊。

    #include <iostream>
    #include <cstring>
    using namespace std;
    const int MOD = 1e9+7;
    const int N = 202;
    int n,dp[N][N][N][2];
    char s[N]; int slen;
    int fail[N][2],nex[N];
    
    void getFail() {
        int j=0;
        nex[0] = nex[1] = 0;
        for(int i=1;i<slen;i++) {
            while(j>0 && s[i]!=s[j]) j=nex[j];
            if(s[i]==s[j]) j++;
            nex[i+1] = j;
        }
    
        if (s[0] == '(') fail[0][0] = 1;
        if (s[0] == ')') fail[0][1] = 1;
        for(int i=1;i<=slen;i++) {
            int pos=i;
            while(pos && s[pos]!='(') pos=nex[pos];
            fail[i][0] = pos+1;
            if(pos==0&&s[0]==')') fail[i][0]=0;
            
            pos = i;
            while(pos && s[pos]!=')') pos=nex[pos];
            fail[i][1] = pos+1;
            if(pos==0&&s[0]=='(') fail[i][1]=0;
        }
    }
    
    int main() {
        scanf("%d%s", &n, s);
        slen = strlen(s);
        getFail();
        dp[0][0][0][0]=1;
        for(int i=0;i<2*n;i++){
            for(int j=0;j<=n;j++){
                for(int k=0;k<=slen;k++){
                    for(int state=0;state<2;state++)
                        if(s[k]=='(') 
                        {
                            (dp[i+1][j+1][k+1][state] += dp[i][j][k][state]) %= MOD;
                            if(j) (dp[i+1][j-1][fail[k][1]][state] += dp[i][j][k][state]) %= MOD;
                        } else
                        if(s[k]==')')
                        {
                            (dp[i+1][j+1][fail[k][0]][state] += dp[i][j][k][state]) %= MOD;
                            if(j) (dp[i+1][j-1][k+1][state] += dp[i][j][k][state]) %= MOD;
                        } else if(state == 1) {
                            (dp[i+1][j+1][fail[k][0]][1] += dp[i][j][k][0]) %= MOD;
                            if(j) (dp[i+1][j-1][fail[k][1]][1] += dp[i][j][k][0]) %= MOD;            
                            (dp[i+1][j+1][fail[k][0]][1] += dp[i][j][k][1]) %= MOD;
                            if(j) (dp[i+1][j-1][fail[k][1]][1] += dp[i][j][k][1]) %= MOD;  
                        }
                }
            }
        }
        int ans=0;
        for(int i=0;i<=slen;i++){
            (ans += dp[2*n][0][i][1]) %= MOD;
        }
        (ans += dp[2*n][0][slen][0]) %= MOD;
        cout<<ans<<endl;
    }
    
    
    

    不妨这么来设计状态。

    pos < strlen(s)

    dp[len][prefix][pos]: 前len位,左括号比右括号多prefix,与串s匹配到了第pos个位置的方案数。

    pos = strlen(s)

    dp[len][prefix][pos]: 前len位,左括号比右括号多prefix,存在和s相等的子串的方案数。

    转移会舒适一点。

    #include <iostream>
    #include <cstring>
    using namespace std;
    const int MOD = 1e9+7;
    const int N = 202;
    int n,dp[N][N][N];
    char s[N]; int slen;
    int fail[N][2],nex[N];
    
    void getFail() {
        int j=0;
        nex[0] = nex[1] = 0;
        for(int i=1;i<slen;i++) {
            while(j>0 && s[i]!=s[j]) j=nex[j];
            if(s[i]==s[j]) j++;
            nex[i+1] = j;
        }
        //printf("len = %d
    ", slen);
        if (s[0] == '(') fail[0][0] = 1;
        if (s[0] == ')') fail[0][1] = 1;
        for(int i=1;i<=slen;i++) {
            int pos=i;
            while(pos && s[pos]!='(') pos=nex[pos];
            fail[i][0] = pos+1;
            if(pos==0&&s[0]==')') fail[i][0]=0;
            
            pos = i;
            while(pos && s[pos]!=')') pos=nex[pos];
            fail[i][1] = pos+1;
            if(pos==0&&s[0]=='(') fail[i][1]=0;
    
            //printf("i=%d %d %d
    ", i,fail[i][0],fail[i][1]);
        }
    }
    
    int main() {
        scanf("%d%s", &n, s);
        slen = strlen(s);
        getFail();
        dp[0][0][0]=1;
        for(int i=0;i<2*n;i++){
            for(int j=0;j<=n;j++){
                for(int k=0;k<slen;k++){
                    if(s[k]=='(') 
                    {
                        (dp[i+1][j+1][k+1] += dp[i][j][k]) %= MOD;
                        if(j) (dp[i+1][j-1][fail[k][1]] += dp[i][j][k]) %= MOD;
                    } else
                    if(s[k]==')')
                    {
                        (dp[i+1][j+1][fail[k][0]] += dp[i][j][k]) %= MOD;
                        if(j) (dp[i+1][j-1][k+1] += dp[i][j][k]) %= MOD;
                    } 
                }
                (dp[i+1][j+1][slen] += dp[i][j][slen]) %= MOD;
                if(j) (dp[i+1][j-1][slen] += dp[i][j][slen]) %= MOD;
            }
        }
        int ans=dp[2*n][0][slen];
        cout<<ans<<endl;
    }
    
    
  • 相关阅读:
    webservice的cxf的客户端
    webservice用cxf发布SOAP
    webservice声明发布SOAP1.2
    webservice使用注解修改WSDL内容
    webservice获取天气信息
    结巴分词原理介绍
    Pytorch学习记录-torchtext和Pytorch的实例( 使用神经网络训练Seq2Seq代码)
    【Pandas】Pandas求某列字符串的长度,总结经验教训
    UTF-8与UTF-8 BOM
    logging.basicConfig函数
  • 原文地址:https://www.cnblogs.com/RUSH-D-CAT/p/9399175.html
Copyright © 2011-2022 走看看