AC自动机 多模式串匹配 模板

AC自动机就是字典树+KMP,解决了一个串在字典树中的匹配问题。

const int maxn = 26;
struct node{
    node* fail;  node* next[maxn];
    int counts;
    node(){
       fail = NULL;
       counts = 0;
       for(int i = 0; i < maxn; ++i)
        next[i] = NULL;
   }
};

struct Trie{
    node* root;
    queue<node*> q;
    Trie(){root = NULL;}

    void inserts(char str[]){
        int len = strlen(str);
        if(!root)
            root = new node;
        node* now = root;
        for(int i = 0; i < len; ++i){
            int idx = str[i]-'a';//transform
            if(now->next[idx] == NULL)
                now->next[idx] = new node;
            now = now->next[idx];
        }
        ++(now->counts);//the counts of the words that suffix match
    }
    void build_fail(){
        root->fail = NULL;
        q.push(root);
        while(!q.empty()){
            node* now = q.front();  q.pop();
            node* jump = NULL;
            for(int i = 0; i < maxn; ++i){
                if(now->next[i] != NULL){
                    jump = now->fail;
                    while(jump != NULL){
                        if(jump->next[i] != NULL){//equal
                            now->next[i]->fail = jump->next[i];
                            break;
                        }
                        jump = jump->fail;
                    }
                    if(jump == NULL)//reach root
                        now->next[i]->fail = root;
                    q.push(now->next[i]);
                }
            }
        }
    }
    int query(char str[]){//return the count of the Tree-words in str
        int ans = 0, idx, len = strlen(str);
        node* p = root;
        for(int i = 0; i < len; ++i){
            idx = str[i]-'a';transform
            while(p->next[idx]==NULL && p!=root)
                p = p->fail;
            p = (p->next[idx]==NULL) ? root : p->next[idx];
            node* jump = p;
            while(jump != root && jump->counts > 0){//find the words that suffix match
                ans += jump->counts;
                jump->counts = 0;//avoid repeat
                jump = jump->fail;
            }
        }
        return ans;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值