首页 > 代码库 > poj 1625 (AC自动机好模版,大数好模版)

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("\n");    }    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("\n");    }    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

 

poj 1625 (AC自动机好模版,大数好模版)