zoukankan      html  css  js  c++  java
  • AC自动机模板

    这里仅以hdu 2222的题目的自动机为模板。

    该模板来自于http://www.bilibili.com/video/av6295004/index_2.html

    #include<bits/stdc++.h>
    
    const int MAX_N = 1e6 + 5;
    const int MAX_Tot = 500005;
    ///Trie + KMP的利用
    struct Aho{
        struct state{
            int next[26];
            int fail, cnt;//fail指针指向失配点,失配点一般寻找他父亲节点的失配点。 然后cnt就表示出现的次数
        }stateTable[MAX_Tot];
    
        int size;
        std::queue<int> que;
    
        void init(){//初始化
            for (int i = 0; i < MAX_Tot; i++){
                memset(stateTable[i].next, 0, sizeof(stateTable[i].next));
                stateTable[i].fail = stateTable[i].cnt = 0;
            }
            while (!que.empty()) que.pop();
            size = 1;
        }
    
        void insert(char *S){//构建Trie树
            int n = strlen(S);
            int now = 0;
            for (int i = 0; i < n; i++){
                char c = S[i];
                if (!stateTable[now].next[c - 'a'])
                    stateTable[now].next[c - 'a'] = size++;
                now = stateTable[now].next[c - 'a'];
            }
            stateTable[now].cnt++;
        }
        
        //构建AC自动机
        void build(){//由于构建AC自动机是需要提前知道父亲节点的失配指针的,且其他结点的也需要知道。所以这里用bfs,因为失配指针的长度不可能长于目前长度
            stateTable[0].fail = -1;//根节点的是失配指针不存在,所以为-1
            que.push(0);
            while (!que.empty()){
                int u = que.front(); que.pop();
                for (int i = 0; i < 26; i++){
                    if (stateTable[u].next[i]){//如果存在子节点的话
                        if (u == 0) stateTable[stateTable[u].next[i]].fail = 0;//根节点的儿子节点的失配全为0
                        else {
                            int v = stateTable[u].fail;
                            while (v != -1){
                                if (stateTable[v].next[i]){//找到失配点
                                    stateTable[stateTable[u].next[i]].fail = stateTable[v].next[i];
                                    break;
                                }
                                v = stateTable[v].fail;
                            }
                            if (v == -1) stateTable[stateTable[u].next[i]].fail = 0;//没有找到失配点,那么就重新从0开始出发
                        }
                        que.push(stateTable[u].next[i]);
                    }
                }
            }
        }
    
        inline int cal(int u){
            int res = 0;
            while (u){
                res += stateTable[u].cnt;
                stateTable[u].cnt = 0;//因为每个串只需要计算一次,所以这里要对cnt进行清空
                u = stateTable[u].fail;
            }
            return res;
        }
    
        int match(char *S){
            int n = strlen(S);
            int res = 0, now = 0;
            for (int i = 0; i < n; i++){
                char c = S[i];
                if (stateTable[now].next[c - 'a'])//如果存在子节点,则继续往下搜
                    now = stateTable[now].next[c - 'a'];
                else {//如果不存在,则沿失配边走。
                    int p = stateTable[now].fail;
                    while (p != -1 && stateTable[p].next[c - 'a'] == 0) p = stateTable[p].fail;
                    if (p == -1) now = 0;//如果没有找到失配点,则另now = 根节点
                    else now = stateTable[p].next[c - 'a'];
                }
                if (stateTable[now].cnt)
                    res += cal(now);
            }
            return res;
        }
    }aho;
    
    char ch[MAX_N];
  • 相关阅读:
    如何用JS判断身份证格式
    ELK+log4j笔记
    JQM进阶:page事件执行过程
    jqm入门页面及对话框
    windows下mongodb的安装
    Bootstarp相关类
    兼容性及相关问题总结
    浏览器加载和渲染html的顺序
    【转】关于top、clientTop、scrollTop、offsetTop等
    pl_sql操作--激活提升权限scott用户
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6371126.html
Copyright © 2011-2022 走看看