码迷,mamicode.com
首页 > 其他好文 > 详细

ac自动机模板

时间:2018-08-12 17:22:46      阅读:138      评论:0      收藏:0      [点我收藏+]

标签:pair   main   bit   queue   onclick   close   sed   can   init   

技术分享图片
int n;
char s[N];
struct Ac {
    int val[N], ch[N][26], f[N], cnt, SZ;

    void init(int SZ = 26) {
        cnt = 0; this->SZ = SZ;
        for(int c = 0; c < SZ; c++) ch[0][c] = 0;
    }

    int getId(char c) {
        return c - a;
    }

    int newNode() {
        cnt++;
        memset(ch[cnt], 0, sizeof(ch[cnt]));
        val[cnt] = f[cnt] = 0;
        return cnt;
    }

    void add(char *s) {
        int u = 0;
        for(int i = 0; s[i]; i++) {
            int c = getId(s[i]);
            if(!ch[u][c]) ch[u][c] = newNode();
            u = ch[u][c];
        }
        val[u]++;
    }

    void build() {
        queue<int> que;
        f[0] = 0;
        for(int c = 0; c < SZ; c++) {
            if(!ch[0][c]) continue;
            f[ch[0][c]] = 0;
            que.push(ch[0][c]);
        }
        while(!que.empty()) {
            int u = que.front(); que.pop();
            for(int c = 0; c < SZ; c++) {
                if(!ch[u][c]) continue;
                int v = ch[u][c], w = f[u];
                while(w && !ch[w][c]) w = f[w];
                f[v] = ch[w][c];
                que.push(v);
            }
        }
    }

    LL cal(char *s) {
        LL ans = 0;
        for(int i = 0, j; s[i]; i++) {
            int c = getId(s[i]);
            while(j && !ch[j][c]) j = f[j];
            j = ch[j][c];
            int p = j;
            while(p && val[p] != -1) {
                ans += val[p];
                val[p] = -1;
                p = f[p];
            }
        }
        return ans;
    }
} ac;

int main() {
    int T; scanf("%d", &T);
    while(T--) {
        ac.init(26);
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%s", s);
            ac.add(s);
        }

        ac.build();

        scanf("%s", s);
        printf("%lld\n", ac.cal(s));
    }
    return 0;
}
View Code

 

带后缀链接的

技术分享图片
#include<bits/stdc++.h>
#define LL long long
#define ll long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>
#define y1 skldjfskldjg
#define y2 skldfjsklejg

using namespace std;

const int N = 1e6 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;

int n;
char s[N];
struct Ac {
    int val[N], ch[N][26], f[N], last[N], cnt, SZ;

    void init(int SZ = 26) {
        cnt = 0; this->SZ = SZ;
        for(int c = 0; c < SZ; c++) ch[0][c] = 0;
    }

    int getId(char c) {
        return c - a;
    }

    int newNode() {
        cnt++;
        memset(ch[cnt], 0, sizeof(ch[cnt]));
        val[cnt] = f[cnt] = last[cnt] = 0;
        return cnt;
    }

    void add(char *s) {
        int u = 0;
        for(int i = 0; s[i]; i++) {
            int c = getId(s[i]);
            if(!ch[u][c]) ch[u][c] = newNode();
            u = ch[u][c];
        }
        val[u]++;
    }

    void build() {
        queue<int> que;
        f[0] = 0;
        for(int c = 0; c < SZ; c++) {
            if(!ch[0][c]) continue;
            f[ch[0][c]] = last[ch[0][c]] = 0;
            que.push(ch[0][c]);
        }
        while(!que.empty()) {
            int u = que.front(); que.pop();
            for(int c = 0; c < SZ; c++) {
                if(!ch[u][c]) continue;
                int v = ch[u][c], w = f[u];
                while(w && !ch[w][c]) w = f[w];
                f[v] = ch[w][c];
                last[v] = val[f[v]] ? f[v] : last[f[v]];
                que.push(v);
            }
        }
    }

    LL cal(char *s) {
        LL ans = 0;
        for(int i = 0, j; s[i]; i++) {
            int c = getId(s[i]);
            while(j && !ch[j][c]) j = f[j];
            j = ch[j][c];
            int p = j;
            while(p && val[p] != -1) {
                ans += val[p];
                val[p] = -1;
                p = last[p];
            }
        }
        return ans;
    }
} ac;

int main() {
    int T; scanf("%d", &T);
    while(T--) {
        ac.init(26);
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%s", s);
            ac.add(s);
        }

        ac.build();

        scanf("%s", s);
        printf("%lld\n", ac.cal(s));
    }
    return 0;
}


/*
*/
View Code

 

ac自动机模板

标签:pair   main   bit   queue   onclick   close   sed   can   init   

原文地址:https://www.cnblogs.com/CJLHY/p/9463054.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!