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;
}

 

  

 

posted @ 2017-04-23 18:59  meekyan  阅读(351)  评论(0编辑  收藏  举报