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;
}


来一发静态数组实现的,毕竟数组型的才能和其他算法结合使用~~~

#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 AC_AUTO {
    int next[26] ;
    int fail ;
    int num ;
    void init() {
        memset(next,0,sizeof(next)) ;
        fail = -1 ;
        num = 0 ;
    }
} a[500000];
int cnt;
char keyword[55];
char str[1111111];

void insert(char *s) {
    int p = 0 ;
    for(int i = 0 ; s[i] ; i ++) {
        int t = s[i] - 'a' ;
        if(a[p].next[t] == 0) {
            a[cnt].init();
            a[p].next[t] = cnt ++;
        }
        p = a[p].next[t] ;
    }
    a[p].num ++;
}
int q[511111] ;
void ac_bfs() {
    int i,head = 0,tail = 0;
    q[tail ++] = 0;
    while(head < tail) {
        int front = q[head ++];
        for(i = 0; i < 26 ; i ++) {
            if(a[front].next[i] != 0) {
                int p = a[front].fail ;
                while(p != -1) {
                    if(a[p].next[i] != 0) {
                        a[a[front].next[i]].fail = a[p].next[i] ;
                        break ;
                    }
                    p = a[p].fail ;
                }
                if(p == -1) a[a[front].next[i]].fail = 0 ;
                q[tail ++] = a[front].next[i] ;
            }
        }
    }
}

int query() {
    int sum = 0,len = strlen(str);
    int p = 0 ;
    for(int i=0; i<len; i++) {
        int t = str[i] - 'a' ;
        while(a[p].next[t] == 0 && p != 0) p = a[p].fail ;
        p = a[p].next[t] ;

        int tmp = p;
        while(tmp != 0 && a[tmp].num != -1) {
            sum += a[tmp].num ;
            a[tmp].num = -1 ;
            tmp = a[tmp].fail ;
        }
    }
    return sum;
}

int main() {
    int T,n;
    scanf("%d",&T);
    while(T --) {
        a[0].init();
        cnt = 1; //注意
        scanf("%d",&n);
        for(int i=0; i<n; i++) {
            scanf("%s",keyword);
            insert(keyword);
        }
        ac_bfs();
        scanf("%s",str);
        printf("%d\n",query());
    }
    return 0;
}


你可能感兴趣的:(HDU 2222 Keywords Search(AC自动机模板题))