HDU 2222 Keywords Search(AC自动机模板题)

学习AC自动机请戳这里:大神blog........

自动机的模板:

 

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <climits>//形如INT_MAX一类的
#define MAX 100005
#define INF 0x7FFFFFFF
#define REP(i,s,t) for(int i=(s);i<=(t);++i)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
#define L(x) x<<1
#define R(x) x<<1|1
# define eps 1e-5
//#pragma comment(linker, "/STACK:36777216") ///传说中的外挂
using namespace std;

struct trie {
    trie *fail; //失败指针
    trie *next[26];
    int cnt;
    trie () {
        fail = 0;cnt = 0;
        memset(next,0,sizeof(next));
    }
}*q[511111]; //模拟队列
trie *rt;
int head,tail;
char keyword[51];
char book[1111111];

void insert(char *key) {
    trie *p = rt;
    int t;
    while(*key) {
        t = *key - 'a';
        if(p->next[t] == NULL) p->next[t] = new trie();
        p = p->next[t];
        key++;
    }
     p->cnt++; //表示一个单词
}

void bfs() {
    rt->fail = NULL; //根结点fail指向空
    q[head++] = rt;
    while(head != tail) {
        trie *t = q[tail++];
        trie *p = NULL;
        for(int i=0; i<26; i++) {
            if(t->next[i] != NULL) {                //对所有儿子的fail指针匹配并且入队
                if(t == rt) t ->next[i]->fail = rt; //如果刚从根节点出发
                else {                              //否则沿着他父亲的失败指针走,
                    //直到走到一个节点,他的儿子中也有相同字符的节点。然后把当前节点的失败指针指向他的那个儿子
                    p = t->fail;
                    while(p != NULL) {
                        if(p->next[i] != NULL) {
                            t->next[i]->fail = p->next[i];
                            break;
                        }
                        p = p->fail;
                    }
                    if(p == NULL) t->next[i]->fail = rt; //如果一直走到了root都没找到,那就把失败指针指向root
                }
                q[head++] = t->next[i];
            }
        }
    }
}

int query(char *key) {
    trie *p = rt;
    int cnt = 0;
    while(*key) {
        int t = *key - 'a';
        while(p->next[t] == NULL && p != rt) p = p->fail; //如果当前字符不匹配
        p = p->next[t];
        if(p == NULL) p = rt; //最终还是未匹配
        trie *tmp = p;
        while(tmp != rt && tmp->cnt != -1) {
            cnt += tmp->cnt;
            tmp->cnt = -1;    //该处已经出现过了
            tmp = tmp->fail;
        }
        key++;
    }
    return cnt;
}
int main(){
    int T;
    cin >> T;
    while(T --) {
        rt = new trie();
        int n;
        cin >> n;
        for(int i=0; i<n; i++) {
            scanf("%s",keyword);
            insert(keyword);
        }
        head = 0; tail = 0;
        bfs();
        scanf("%s",book);
        printf("%d\n",query(book));
    }
    return 0;
}


 

 

posted on 2013-07-31 19:34  you Richer  阅读(150)  评论(0编辑  收藏  举报