HDU 3695 (AC自动机)

来源:互联网 发布:纱裙布料淘宝 编辑:程序博客网 时间:2024/04/30 06:25

题目链接:点击这里

题意:求文本串中出现的模式串个数。模式串反着出现也算。

把模式串正反都扔进自动机,节点开一个vector存下来所有的以这个节点结尾的模式串,然后扫一遍就行了。注意正反算一种

trick:q不是只有一位

#include <cstdio>#include <cmath>#include <algorithm>#include <iostream>#include <vector>#include <queue>#include <cstring>using namespace std;#define maxn 500005#define maxm 5100005int n;struct trie {    int next[maxn][26], fail[maxn];    vector <int> end[maxn];    bool vis[maxn];    int root, cnt;    int new_node () {        memset (next[cnt], -1, sizeof next[cnt]);        end[cnt++].clear ();        return cnt-1;    }    void init () {        memset (vis, 0, sizeof vis);        cnt = 0;        root = new_node ();    }    void insert (char *buf, int pos) {//字典树插入一个单词        int len = strlen (buf);        int now = root;        for (int i = 0; i < len; i++) {            int id = buf[i]-'A';            if (next[now][id] == -1) {                next[now][id] = new_node ();            }            now = next[now][id];        }        end[now].push_back (pos);    }    void build () {//构建fail指针        queue <int> q;        fail[root] = root;        for (int i = 0; i < 26; i++) {            if (next[root][i] == -1) {                next[root][i] = root;            }            else {                fail[next[root][i]] = root;                q.push (next[root][i]);            }        }        while (!q.empty ()) {            int now = q.front (); q.pop ();            for (int i = 0; i < 26; i++) {                if (next[now][i] == -1) {                    next[now][i] = next[fail[now]][i];                }                else {                    fail[next[now][i]] = next[fail[now]][i];                    q.push (next[now][i]);                }            }        }    }    int query (char *buf) {        int len = strlen (buf);        int now = root;        int res = 0;        for (int i = 0; i < len; i++) {            int id = buf[i]-'A';            now = next[now][id];            int tmp = now;            while (tmp != root) {                int Max = end[tmp].size ();                if (Max) {                    for (int j = 0; j < Max; j++) {                        vis[end[tmp][j]] = 1;                    }                    end[tmp].clear ();                }                else                     break;                tmp = fail[tmp];//沿着失配边走            }        }        for (int i = 0; i < n; i++) if (vis[i] || vis[i+n])             res++;        return res;    }}ac;char a[maxm], b[maxm];void deal () {    int len = 0;    int n = strlen (a);    for (int i = 0; i < n; i++) {        if (a[i] != '[') {            b[len++] = a[i];            continue;        }        i++;        int num = 0;        while (a[i] <= '9' && a[i] >= '0') {            num = num*10+a[i]-'0';            i++;        }        for (int j = 0; j < num; j++) b[len++] = a[i];        i++;    }    b[len] = 0;}int main () {    int t;    scanf ("%d", &t);    while (t--) {        scanf ("%d", &n);         ac.init ();        for (int i = 0; i < n; i++) {             scanf ("%s", a);            ac.insert (a, i);            int len = strlen (a);            for (int j = 0; j < len/2; j++) {                swap (a[j], a[len-j-1]);            }            ac.insert (a, i+n);        }          ac.build ();        scanf ("%s", a);        deal ();        printf ("%d\n", ac.query (b));    }    return 0;}
0 0
原创粉丝点击