zoukankan      html  css  js  c++  java
  • 2016-2017 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2016) E.Passwords AC自动机+dp

    题目链接点这里

    题意:

      让你构造一个长度范围在[A,B]之间 字符串(大小写字母,数字),问你有多少种方案

      需要满足条件一下:

        1:构成串中至少包含一个数字,一个大写字母,一个小写字母;

          2:不能包含给定的N个病毒串

               3:遵循一堆映射规则

    题解:

      将病毒串建立AC自动机

      设定dp[i][j] [0/1][0/1][0/1]:表示构造长度为i,在自动机上面的状态是j,分别是否含有数字,大写字母,小写字母的情况

      你能转移的点就是 加上一个数字或者大小写字母,暴力转移DP就好了,方程复杂度:20*1000*8,转移复杂度:26+26+10

      整体复杂度:20*1000*8*62+建立trie

    #include<bits/stdc++.h>
    using namespace std;
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double Pi = acos(-1.0);
    const int N = 1e6+10, M = 1e3+20;
    LL mod = 1000003;
    int nex[5500][70],q[55000],fail[5500],cnt=1,black[55000],head,tail;
    int rea_ID(int ch) {
        if(ch >= 0 && ch < 26) return ch;
        if(ch == 26) return 'o'-'a';
        if(ch == 27) return 'i'-'a';
        if(ch == 29) return 'e'-'a';
        if(ch == 31) return 's'-'a';
        if(ch == 33) return 't'-'a';
        if(ch >= 26 && ch <= 35) return 26;
        if(ch > 35 && ch <= 61)return ch - 36;
    }
    int ID(char ch) {
        return ch - 'a';
    }
    void insert(char *s) {
        int now = 1, len = strlen(s);
        for(int i = 0; i < len; ++i) {
            int index = ID(s[i]);
            if(!nex[now][index])
                nex[now][index] = ++cnt;
            now = nex[now][index];
        }
        black[now] |= 1;
    }
    void build_fail() {
        head = 0, tail = 0;
        for(int i = 0; i < 26; ++i) nex[0][i] = 1;
        fail[1] = 0;
        q[tail++] = 1;
        while(head != tail) {
            int now = q[head++];
            black[now] |= black[fail[now]];
            for(int i = 0; i < 26; ++i) {
                int p = fail[now];
                if(!nex[now][i]) {
                    nex[now][i] = nex[p][i];continue;
                }
                fail[nex[now][i]] = nex[p][i];
                q[tail++] = nex[now][i];
            }
            nex[now][26] = 1;
        }
    }
    int A,B,n;
    char s[500];
    LL dp[30][5500][2][2][2];
    int main()
    {
        scanf("%d%d",&A,&B);
        scanf("%d",&n);
        for(int i = 1; i <= n; ++i) {
            scanf("%s",s);
            insert(s);
        }
        build_fail();
        dp[0][1][0][0][0] = 1;
        for(int i = 0; i <= B; ++i) {
            for(int j = 1; j <= cnt; ++j) {
                for(int dxziok = 0; dxziok <= 1; ++dxziok)
                for(int shuziok = 0; shuziok <= 1; ++shuziok)
                for(int xxziok = 0; xxziok <= 1; ++xxziok) {
                    if(dp[i][j][dxziok][shuziok][xxziok] == 0) continue;
                    for(int k = 0; k <= 61; ++k) {
                        int rea = rea_ID(k);
                        int tmp1 = 0,tmp2 = 0,tmp3 = 0;
                        if(k < 26) tmp1 = 1;
                        else if(k <= 35) tmp2 = 1;
                        else tmp3 = 1;
                        if(!black[nex[j][rea]])
                            dp[i+1][nex[j][rea]][dxziok|tmp1][shuziok|tmp2][xxziok|tmp3] +=
                            dp[i][j][dxziok][shuziok][xxziok];
                            dp[i+1][nex[j][rea]][dxziok|tmp1][shuziok|tmp2][xxziok|tmp3]%=mod;
                    }
                }
    
            }
        }
        LL ans = 0;
        for(int i = A; i <= B; ++i) {
            for(int j = 1; j <= cnt; ++j) {
                    ans = (ans + dp[i][j][1][1][1])%mod;
                }
            }
        cout<<ans<<endl;
        return 0;
    }

      

  • 相关阅读:
    Java面向对象基本/传参/引用/访问控制/构造器
    二叉树遍历&分治
    Java基础 & 基本数据类型 & String类
    Java面向对象继承/重写/多态
    Java集合基础
    Java面向对象抽象类/接口类/内部类
    你碰我变
    cookie&&localstorage
    父亲的谎话,只有长大后才能听懂……
    CSS的兼容性
  • 原文地址:https://www.cnblogs.com/zxhl/p/6753480.html
Copyright © 2011-2022 走看看