zoukankan      html  css  js  c++  java
  • poj 1625 (AC自动机好模版,大数好模版)

    题目

    给n个字母,构成长度为m的串,总共有n^m种。给p个字符串,问n^m种字符串中不包含(不是子串)这p个字符串的个数。

    将p个不能包含的字符串建立AC自动机,每个结点用val值来标记以当前节点为后缀的字符串是否包含非法字符串(p个字符串中的任何一个)。

    状态转移方程:f(i, j)  += f(i-1, k)  

    f(i, j)表示长度为i的字符串,结尾为字符j,方程j和k的关系可以从自动机中失配关系直接获得(j是k的后继结点)。

    总之感觉是好东西,快存下来

    大数模版:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    struct BigInteger{
        int A[25];
        enum{MOD = 10000};
        BigInteger(){memset(A, 0, sizeof(A)); A[0]=1;}
        void set(int x){memset(A, 0, sizeof(A)); A[0]=1; A[1]=x;}
        void print(){
            printf("%d", A[A[0]]);
            for (int i=A[0]-1; i>0; i--){
                if (A[i]==0){printf("0000"); continue;}
                for (int k=10; k*A[i]<MOD; k*=10) printf("0");
                printf("%d", A[i]);
            }
            printf("
    ");
        }
        int& operator [] (int p) {return A[p];}
        const int& operator [] (int p) const {return A[p];}
        BigInteger operator + (const BigInteger& B){
            BigInteger C;
            C[0]=max(A[0], B[0]);
            for (int i=1; i<=C[0]; i++)
                C[i]+=A[i]+B[i], C[i+1]+=C[i]/MOD, C[i]%=MOD;
            if (C[C[0]+1] > 0) C[0]++;
            return C;
        }
        BigInteger operator * (const BigInteger& B){
            BigInteger C;
            C[0]=A[0]+B[0];
            for (int i=1; i<=A[0]; i++)
                for (int j=1; j<=B[0]; j++){
                    C[i+j-1]+=A[i]*B[j], C[i+j]+=C[i+j-1]/MOD, C[i+j-1]%=MOD;
                }
            if (C[C[0]] == 0) C[0]--;
            return C;
        }
    };
    int main() {
        BigInteger a, b;
        a.set(1); b.set(1);
        (a+b).print();
    
        return 0;
    }
    View Code

    本题答案(内含AC自动机模版):

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <vector>
    #include <queue>
    using namespace std;
    typedef unsigned char uchar;
    
    struct AC_Automata {
        #define N 102
        int ch[N][55], val[N], last[N], f[N], sz;
        void clear() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); }
    
        int hash[256], M;
        void set_hash(int n, uchar s[]) {
            M = n; for (int i=0; i<n; i++) hash[s[i]] = i;
        }
        void insert(uchar s[], int v) {
            int u = 0;
            for (int i=0; s[i]; i++) {
                int c = hash[s[i]];
                if (!ch[u][c]) {
                    memset(ch[sz], 0, sizeof(ch[sz]));
                    val[sz] = 0;
                    ch[u][c] = sz++;
                }
                u = ch[u][c];
            }
            val[u] = v;  //标记当前串为非法的
        }
        void build() {
            queue<int> q;
            f[0] = 0;
            for (int c=0; c<M; c++) {
                int u = ch[0][c];
                if (u) { f[u] = last[u] = 0; q.push(u); }
            }
            while (!q.empty()) {
                int r = q.front(); q.pop();
                for (int c=0; c<M; c++) {
                    int u = ch[r][c];
                    val[r] = val[r] || val[f[r]];   //判断当前结点是否有非法后缀
                    if (!u) {
                        ch[r][c] = ch[f[r]][c];
                        continue;
                    }
                    q.push(u);
                    f[u] = ch[f[r]][c];
                    last[u] = val[f[u]] ? f[u] : last[f[u]];
                }
            }
        }
    } ac;
    struct BigInteger{
        int A[25];
        enum{MOD = 10000};
        BigInteger(){memset(A, 0, sizeof(A)); A[0]=1;}
        void set(int x){memset(A, 0, sizeof(A)); A[0]=1; A[1]=x;}
        void print(){
            printf("%d", A[A[0]]);
            for (int i=A[0]-1; i>0; i--){
                if (A[i]==0){printf("0000"); continue;}
                for (int k=10; k*A[i]<MOD; k*=10) printf("0");
                printf("%d", A[i]);
            }
            printf("
    ");
        }
        int& operator [] (int p) {return A[p];}
        const int& operator [] (int p) const {return A[p];}
        BigInteger operator + (const BigInteger& B){
            BigInteger C;
            C[0]=max(A[0], B[0]);
            for (int i=1; i<=C[0]; i++)
                C[i]+=A[i]+B[i], C[i+1]+=C[i]/MOD, C[i]%=MOD;
            if (C[C[0]+1] > 0) C[0]++;
            return C;
        }
        BigInteger operator * (const BigInteger& B){
            BigInteger C;
            C[0]=A[0]+B[0];
            for (int i=1; i<=A[0]; i++)
                for (int j=1; j<=B[0]; j++){
                    C[i+j-1]+=A[i]*B[j], C[i+j]+=C[i+j-1]/MOD, C[i+j-1]%=MOD;
                }
            if (C[C[0]] == 0) C[0]--;
            return C;
        }
    };
    int n, m, p;
    uchar s[55];
    
    int main() {
    
        while (scanf("%d %d %d ", &n, &m, &p) == 3) {
            ac.clear();
            cin >> s; ac.set_hash(n, s);
            while (p--) {
                cin >> s; ac.insert(s, 1);
            }
            ac.build();
    
            BigInteger f[51][101];
            f[0][0].set(1);
    
            for (int i=1; i<=m; i++)
                for (int j=0; j<ac.sz; j++)
                    for (int k=0; k<n; k++) {
                        int u = ac.ch[j][k];
                        if (!ac.val[u]) f[i][u] = f[i][u] + f[i-1][j];
                    }
            BigInteger ans;
            for (int i=0; i<ac.sz; i++)
                if (!ac.val[i]) ans = ans + f[m][i];
            ans.print();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    windows定时关机命令
    centos 共享文件目录
    Linux 虚拟机的安全加固建议
    使用mondorescue将本机linux centos 7服务器制作成光盘
    CentOS 7 救援模式启用网卡及重新获取IP地址
    CentOS 7修复MBR和GRUB
    使用windows性能计数器监控cpu使用率
    CodeForces-916A-jamie and Alarm Snooze(笨比题目)
    CodeForces-721D-Maxim and Array(优先队列,贪心,分类讨论)
    CodeForces-721C-Journey(DAG, DP)
  • 原文地址:https://www.cnblogs.com/laiba2004/p/4004417.html
Copyright © 2011-2022 走看看