【HDU-2222】Keywords Search(AC自动机模板)

AC自动机的模板题,自己手敲了一遍模板。

添加失配边的时候,对每个结点的26条字母边链接的子结点扫一遍,如果结点存在,那么这个子结点的失配边就是主结点失配边对应结点链接的子节点。

如果结点不存在,那么这个结点就直接连到主结点失配边对应结点链接的子节点。

感觉AC自动机好难懂啊。。。QAQ

11885512 2014-10-16 16:22:43 Accepted 2222 687MS 26688K 2772 B G++ KinderRiven

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 555555;
const int maxn_sign = 26;
const int maxd = 1111111;
int root;
struct Trie{ //AC自动机
    int tr[maxn][maxn_sign];//Trie树
    int fail[maxn]; //失配边
    int val[maxn];
    int sz; //总结点数
    int counts;
    int index(int c){
        if(c >= 'a' && c <= 'z')
            return c - 'a';
        if(c >= 'A' && c <= 'Z')
            return c - 'A';
    }
    void init(){   //树的初始化
        sz = 0; val[0] = 0; counts = 0;
        for(int i = 0; i < 26; i++) tr[0][i] = -1;
    }
    int newnode(){ //申请新的结点
        val[sz] = 0;
        for(int i = 0; i < 26; i++) tr[sz][i] = -1;
        sz ++;
        return sz - 1;
    }
    void insert(char *str){
         int u = 0,n = strlen(str);
         for(int i = 0; i < n; i++){
            int e = index(str[i]);
            if(tr[u][e] == -1){  //没有这个结点
                int d = newnode();
                tr[u][e] = d;
            }
            u = tr[u][e];
         }
         val[u] ++;
    }
    void buildfail(){
        queueq;
        fail[root] = root; //根结点的失配边连向自己
        for(int i = 0; i < 26; i++){
            if(tr[root][i] == -1)
               tr[root][i] = root;
            else{
                q.push(tr[root][i]);
                fail[tr[root][i]] = root;
            }
        }
        while(!q.empty()){
            int node = q.front(); q.pop();
            for(int i = 0; i < 26; i++){
                if(tr[node][i] == -1){
                   tr[node][i] = tr[fail[node]][i];
                }
                else{
                    fail[tr[node][i]] = tr[fail[node]][i];
                    q.push(tr[node][i]);
                }
            }
        }
    }
    void triecount(char *str){
         int L = strlen(str);
         int u = 0;
         for(int i = 0; i < L;i ++){
            u = tr[u][index(str[i])];
            int temp = u;
            while(temp != root){
                counts += val[temp];
                val[temp] = 0;
                temp = fail[temp];
            }
         }
    }
};
Trie ac;
char s[maxd];
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        ac.init();
        int n;
        root = ac.newnode();
        char str[55];
        scanf("%d",&n);
        for(int i = 0; i < n; i++){
            scanf("%s",str);
            ac.insert(str);
        }
        scanf("%s",s);
        ac.buildfail();
        ac.triecount(s);
        printf("%d\n",ac.counts);
        //printf("%d\n",ac.sz);
    }
    return 0;
}

你可能感兴趣的:(数据结构)