hdu 2222 Keywords Search(AC自动机)

来源:互联网 发布:js 防水 编辑:程序博客网 时间:2024/06/15 09:21

AC自动机练手题。注意题意,keyword可能重复,这些重复的keyword要单独计算。

PS:升级了AC自动机模板 O(∩_∩)O~ 感觉更和谐了


#include <cmath>#include <cstdio>#include <cstdlib>#include <climits>#include <string>#include <cstring>#include <vector>#include <queue>#include <iostream>#include <algorithm>#include <map>#include <set>using namespace std;#define rep(i, s, t) for(int (i)=(s);(i)<=(t);++(i))#define urep(i, s, t) for(int (i)=(s);(i)>=(t);--(i))typedef long long LL;const int inf  = 0x7fffffff;const int Maxn = 100000;struct ACAutomation {    // 最大节点数:模式串个数 * 最大串长度    static const int MAX_NODE = 10000 * 50 + 50;    static const int CHAR_SET = 26;    static const int BASE     = 'a';    int n;                          // trie大小    int id[BASE+CHAR_SET+1];        // 字符->int    int tag[MAX_NODE];              // 标记,根据需要调整    int last[MAX_NODE];             // 后缀链接,链接到上一个单词节点    int fail[MAX_NODE];    int trie[MAX_NODE][CHAR_SET];    void init() {        for (int i=0;i<CHAR_SET;++i)            id[BASE+i] = i;        n = 1;        memset(trie[0], -1, sizeof(trie[0]));        memset(tag, 0, sizeof(tag));        memset(last, 0, sizeof(last));    }    void add(const char *s) {        int p = 0;        while (*s) {            int i = id[*s];            if (trie[p][i] == -1) {                memset(trie[n], -1, sizeof(trie[n]));                trie[p][i] = n++;            }            ++s;            p = trie[p][i];        }        //tag[p] = 1;        tag[p]++;    }    void build() {        queue<int> Q;        fail[0] = 0;        int u, v;        for (int i=0;i<CHAR_SET;++i) {            u = trie[0][i];            if (u != -1) {                fail[u] = 0;                Q.push(u);            }            else                trie[0][i] = 0;        }        while (!Q.empty()) {            int fr = Q.front();Q.pop();            for (int i=0;i<CHAR_SET;++i) {                int &u = trie[fr][i];    // 注意这里使用了一个引用                if ( u != -1 ) {                    Q.push(u);                    fail[u] = trie[fail[fr]][i];                    //tag[u] += tag[fail[u]];                    last[u] = tag[fail[u]] ? fail[u] : last[fail[u]];                }                else                    u = trie[fail[fr]][i];            }        }    }    int search(const char * T, int len) {        int p = 0;        int ret = 0;        for (int i=0;i<len;++i) {            //cout << "on " << T[i] << endl;            if (T[i] < 'a' || T[i] > 'z') {                p = 0;                continue;            }            int c = id[T[i]];            //hile (p && !trie[p][c]) p = fail[p];            p = trie[p][c];            //ret += tag[p];            int v = last[p];            if (tag[p]) {ret += tag[p];tag[p] = 0;}            while (v) {                if (tag[v]) {                    ret += tag[v];                    tag[v] = 0;                }                v = last[v];            }            //cout << "match on node: " << p << " cnt:  " << ret << endl;        }        return ret;    }};string text;ACAutomation ac;int main() {#if 1    freopen("input.in", "r", stdin);#endif    iostream::sync_with_stdio(0);    int T;    cin >> T;    while (T--) {        ac.init();        int n;        cin >> n;        string str;        while (n--) {            cin >> str;            ac.add(str.c_str());        }        cin >> text;        ac.build();        cout << ac.search(text.c_str(), text.length()) << endl;;    }    return 0;}


0 0