【算法练习】HDU3065 病毒侵袭持续中 (AC自动机)

题意

给出n个单词的字典,给出一个文本串,求文本串中每个单词出现了多少次。

题解

AC自动机,还是卡空间。卵用memset就MLE,用不带last就TLE。
所以就改了一蛤。

代码

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int nmax = 50007;
const int sigma = 128;
int occ_times[nmax];
char dictionay[1001][51];
int n,m,cnt;
char str[2000001];
struct Aho {
    int sz;
    queue<int> que;
    struct Node {
        int nxt[sigma];
        bool isocc;
        int fail, id, last;
    } node[nmax];

    void init() {
        memset(node[0].nxt, 0, sizeof node[0].nxt);
        sz = 1;
    }

    inline int idx(const char & ch) {return ch;}

    void insert(char * S, int id) {
        int len = strlen(S);
        int now = 0;
        for(int i = 0; i < len; ++i) {
            int c = idx(S[i]);
            if(!node[now].nxt[c]) {
                memset(node[sz].nxt, 0, sizeof node[sz].nxt);
                node[sz].fail = node[now].isocc = node[sz].isocc = 0;
                node[now].nxt[c] = sz++;
            }
            now = node[now].nxt[c];
        }
        node[now].isocc = true;
        node[now].id = id;
    }

    void build_fail() {
        node[0].fail = 0;
        node[0].last = 0;
        for (int i = 0; i < sigma; ++i) {
            if (node[0].nxt[i]) {
                node[node[0].nxt[i]].fail = 0;
                node[node[0].nxt[i]].last = 0;
                que.push(node[0].nxt[i]);
            }
        }
        while(!que.empty()) {
            int now = que.front(); que.pop();
            for(int i = 0; i < sigma; ++i) {
                int son = node[now].nxt[i];
                if (!son) {
                    node[now].nxt[i] = node[node[now].fail].nxt[i];
                    continue;
                }
                que.push(son);
                node[son].fail = node[node[now].fail].nxt[i];
                node[son].last = node[node[now].fail].isocc ? node[son].fail : node[node[son].fail].last;
            }
        }
    }

    void getans(int u) {
        while(u) {
            if(node[u].isocc)
                occ_times[node[u].id] ++;
            u = node[u].last;
        }
    }

    void match(char * S) {
        int len = strlen(S);
        int now = 0;
        for(int i = 0; i < len; ++i) {
            int c = idx(S[i]);
            now = node[now].nxt[c];
            if (node[now].isocc) {
                getans(now);
            } else if(node[now].last) {
                getans(node[now].last);
            }

        }
    }

} aho;
int main() {
    while(scanf("%d", &n) != EOF) {
        aho.init();
        for(int i = 1; i <= n; ++i) {
            scanf("%s", dictionay[i]);
            aho.insert(dictionay[i], i);
            occ_times[i] = 0;
        }
        aho.build_fail();
        scanf("%s", str);
        aho.match(str);
        for (int i = 1; i <= n; ++i) {
            if(occ_times[i] != 0) {
                printf("%s: ", dictionay[i]);
                printf("%d\n", occ_times[i]);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/pengwill97/article/details/81542280