AC自动机模板(hdu2222-Keywords Search)

地址:http://acm.hdu.edu.cn/showproblem.php?pid=2222

题目参考:http://www.notonlysuccess.com/index.php/aho-corasick-automaton/

此题模板:

#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int Max=250010;
const int MAX_CHILD=27;
int chd[Max][MAX_CHILD],fail[Max],val[Max],ID[128],sz;
char s[50];
queue<int>q;
int Query(const char *s) {
    int ret = 0;
    int cur = 1, tmp;//Trie的根节点为1号节点
    for (int i = 0; s[i]; i++) {
        if (chd[cur][ID[s[i]]]) cur = chd[cur][ID[s[i]]];
        else {
            while (cur != 1 && chd[cur][ID[s[i]]] == 0)
                cur = fail[cur];
            if (chd[cur][ID[s[i]]]) cur = chd[cur][ID[s[i]]];
        }
        tmp = cur;
        while (tmp != 1 && val[tmp] != -1) {
            ret += val[tmp];
            val[tmp] = -1;//单次匹配
            tmp = fail[tmp];
        }
    }
    return ret;
}

void Build_AC() {
    while (!q.empty()) q.pop();
    q.push(1);
    fail[1] = 1;
    while (!q.empty()) {
        int cur = q.front();
        q.pop();
        for (int i = 0; i < MAX_CHILD; i++)
            if (chd[cur][i]) {
                    if (cur == 1) fail[chd[cur][i]] = 1;
                else {
                    int tmp = fail[cur];
                    while (tmp != 1 && chd[tmp][i] == 0) tmp = fail[tmp];
                    if (chd[tmp][i]) fail[chd[cur][i]] = chd[tmp][i];
                    else fail[chd[cur][i]] = 1;
                }
                q.push(chd[cur][i]);
            }
    }
}
void Insert(const char *s){//建一棵Trie树
    int cur=1;
    for(int i=0;s[i];i++)
    {
        if(!chd[cur][ID[s[i]]])chd[cur][ID[s[i]]]=++sz;//sz表示树中一共有多少节点
        cur=chd[cur][ID[s[i]]];
    }
    val[cur]++;
}

char str[1000000];
int main(){
    int t;
    scanf("%d",&t);
    for(int i=0;i<26;i++)
    {
        ID[i+'a']=i;
    }
    while(t--){
        memset(chd,0,sizeof(chd));
        memset(val,0,sizeof(val));
        memset(fail,0,sizeof(fail));
        sz=1;
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf(" %s",s);
            Insert(s);
        }
        Build_AC();
        scanf(" %s",str);
        printf("%d\n",Query(str));
    }
    return 0;
}
View Code

 

posted @ 2013-08-05 19:43  SunnySnail  阅读(182)  评论(0编辑  收藏  举报