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;

}


 

 

你可能感兴趣的:(search)