4.【ac自动机】模式串匹配

ANSI编码的中英文16叉模式串匹配自动机

1.构造模式串树

void insert(char* s, in* trie) {

    long u = 1, len = strlen(s);//每来一个模式串
    for (long i = 0; i < len * 2; i++) {
        if (i % 2 == 0) {
            uint8_t vv = (uint8_t)s[i / 2];
            uint8_t v = vv >> 4;
            if (!trie[u].son[v])
                trie[u].son[v] = ++cnt;
            u = trie[u].son[v];
        }
        else {
            uint8_t vv = ((uint8_t)s[i / 2] << 4);
            uint8_t v = vv >> 4;//s[i]后四位
            if (!trie[u].son[v])
                trie[u].son[v] = ++cnt;
            u = trie[u].son[v];
        }
    }

    trie[u].patternNum++;
    if (strcmp(trie[u].strInfo, s)) {
        strcat(trie[u].strInfo, s);  if (u % 100000 == 0)printf("建树中... %d\n", u);  //不可使用指针!
    }

}

2.得到fail指针

void getFail(in* trie) {
    long u, y;
    for (long i = 0; i < 16; i++) {
        trie[0].son[i] = 1;          //初始化0的所有儿子都是1 所有的树型有限自动机都有一个共同的特点,即对任何输入字符a, 都有g(0, a) != 0。

    }
    queue_push(&q, 1); trie[1].fail = 0;               //将根压入队列
    while (!queue_empty(&q)) {
        queue_front(&q, &u); queue_pop(&q, &y);
        for (long i = 0; i < 16; i++) {              //遍历所有儿子
            long v = trie[u].son[i];           //处理u的i儿子的fail,这样就可以不用记父亲了
            long Fail = trie[u].fail;          //就是fafail,trie[Fail].son[i]就是和v值相同的点
            if (!v) { trie[u].son[i] = trie[Fail].son[i]; continue; }  //不存在该节点,第二种情况
            trie[v].fail = trie[Fail].son[i]; //第三种情况,直接指就可以了
            //printf("%d    %d\n", v, trie[Fail].son[i]);
            queue_push(&q, v);                      //存在实节点才压入队列
        }
    }
}

3.主串查询(不回溯)

long query(char* s, long len, in* trie) {

    long u = 1;
    for (long i = 0; i < len * 2; i++) {
        long k = 0;
        if (i % 2 == 0) {
            uint8_t vv = (uint8_t)s[i / 2];
            uint8_t v = vv >> 4;
            k = trie[u].son[v];
            while (k > 1) {
                count++;
                if (count % 10000000 == 0) printf("查询中...%lld\n", count/1000);
                if (trie[k].strInfo[0] !=‘\0‘) {
                    trie[k].flag++;
                }
                k = trie[k].fail;
            }
            u = trie[u].son[v];

        }
        else {
            uint8_t vv = ((uint8_t)s[i / 2] << 4);
            uint8_t v = vv >> 4;
            k = trie[u].son[v];
            while (k > 1) {
                count++;
                if (count % 10000000 == 0) printf("查询中...%lld\n", count/1000);
                if (trie[k].strInfo[0] != ‘\0‘) {
                    trie[k].flag++;
                }
                k = trie[k].fail;   //继续跳Fail
            }
            u = trie[u].son[v];//到下一个儿子
        }
    }
    return count;
}

4.堆排

void HeapAdjust(txt* data, int s, int m)//s=3,m=7 s=2 s是广义上的根  (下一根 )
{
    txt temp; int  i;
    temp = data[s];//a[3]
    for (i = 2 * s + 1; i <= m; i = i * 2 + 1)//i=7;i<=7; i=5  i为根s的子树结点
    {  //printf("k%d",a[i+1]);
        if (i<m && data[i].appearNum>data[i + 1].appearNum)        //i为小子树
            i++;
        if (!(temp.appearNum > data[i].appearNum))            //初始根根和小子树比较,根小于等于小子树,退出 ; 这个temp根是初始根,并非下一根 子树可能是儿子或孙子...
            break;
        data[s] = data[i];//初始根大于 小子树值 (这里并不一定是父子比较,第二次可能是爷孙比较)s广义根变小子树值
        s = i;//继续判断下一根 直到叶子结点
    }
    data[s] = temp;//叶子结点值变初始根值
}
void HeapSort(txt* data, int size)
{
    int i, j;
    txt temp;
    for (i = (size - 1) / 2; i >= 0; i--)//i=(8-1)/2=3
        HeapAdjust(data, i, size - 1);//a,3,7 a,2,7  a,1,7 a,0,7 循环调整 建立小根堆
    for (i = size - 1; i > 0; i--)
    {
        temp = data[0];
        data[0] = data[i];
        data[i] = temp;
        HeapAdjust(data, 0, i - 1);

    }

}

5.问题:中文2字节编码后,拆成4个16进制,会出现杂糅问题。例如你好(C4E3BAC3)可能识别出愫(E3BA),模式串越短错误率越高,尤其是单字母的英文模式串。但词组错误率几乎为零。256叉树可解决此问题

原文地址:https://www.cnblogs.com/apo2019/p/11957488.html

时间: 2024-10-05 05:01:24

4.【ac自动机】模式串匹配的相关文章

AC自动机——多模式串匹配的算法思想

标准KMP算法用于单一模式串的匹配,即在母串中寻求一个模式串的匹配,但是现在又存在这样的一个问题,如果同时给出多个模式串,要求找到这一系列模式串在母串存在的匹配个数,我们应该如何处理呢? 基于KMP算法,我们能够想到的一个朴素算法就是,枚举这多个模式串,然后进行多次KMP算法,这个过程中完成计数,假设这里有n个模式串,那么整个算法的复杂度大约是O(n*m),m是母串的长度,这里的时间复杂度是粗略估计,没有计算辅助数组的时间(KMP中的next数组),但是这种复杂度还是太高,没有做到KMP算法中“

数据结构与算法简记--多模式字符串匹配AC自动机

AC自动机 一样的不太好理解,有时间再啃 敏感词过滤 单模式字符串匹配算法:(BF,RK,BM,KMP)每次取敏感词字典中一个敏感语做为模式串在用户输入的主串中进行匹配,效率较低 多模式字符串匹配算法:(Trie树,AC自动机) Trie树:把用户输入的内容作为主串,从第一个字符(假设是字符 C)开始,在 Trie 树中匹配.当匹配到 Trie 树的叶子节点,或者中途遇到不匹配字符的时候,我们将主串的开始匹配位置后移一位,也就是从字符 C 的下一个字符开始,重新在 Trie 树中匹配. Trie

AC自动机 - 多模式串匹配问题的基本运用 + 模板题 --- HDU 2222

Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 35655    Accepted Submission(s): 11496 Problem Description In the modern time, Search engine came into the life of everybody like

AC自动机 - 多模式串的匹配运用 --- HDU 2896

病毒侵袭 Problem's Link:http://acm.hdu.edu.cn/showproblem.php?pid=2896 Mean: 中文题,不解释. analyse: AC自动机的运用,多模式串匹配.就是有几个细节要注意,在这些细节上卡了半天了. 1)输出的网站编号和最终的病毒网站数不是一样的: 2)next指针要设128,不然会爆栈: 3)同理,char转换为int时,base要设为31: Time complexity:o(n)+o(ml)  Source code: // M

【暖*墟】 #AC自动机# 多模式串的匹配运用

一.构建步骤 1.将所有模式串构建成 Trie 树 2.对 Trie 上所有节点构建前缀指针(类似kmp中的next数组) 3.利用前缀指针对主串进行匹配 AC自动机关键点一:trie字典树的构建过程 字典树的构建过程是这样的,当要插入许多单词的时候,我们要从前往后遍历整个字符串, 当我们发现当前要插入的字符其节点再先前已经建成,我们直接去考虑下一个字符即可, 当我们发现当前要插入的字符没有再其前一个字符所形成的树下没有自己的节点, 我们就要创建一个新节点来表示这个字符,接下往下遍历其他的字符.

【算法】AC自动机/AC算法 - 多模式串快速匹配

AC自动机 Accepted Aho-Corasick 性质 AC自动机/AC算法(Aho-Corasick automaton),是著名的多模式串匹配算法. 前置知识 字典树(重要) KMP算法(了解Next数组的作用) 典例与算法复杂度分析 典型例题是:给定一个主串 S,给定多个模式串 T,问主串 S 中存在多少个给定的模式串 在KMP算法中,一个长度为n的主串一个长度为m的模式串的复杂度为 O(n+m) 而如果直接照搬KMP算法到这种题型下,模式串处理一次就需要匹配一次 如果有t个模式串,

hdu5384 AC自动机模板题,统计模式串在给定串中出现的个数

http://acm.hdu.edu.cn/showproblem.php?pid=5384 Problem Description Danganronpa is a video game franchise created and developed by Spike Chunsoft, the series' name is compounded from the Japanese words for "bullet" (dangan) and "refutation&q

AC自动机 - AC自动机 - 多模式串的匹配运用 --- HDU 3065

病毒侵袭持续中 Problem's Link:http://acm.hdu.edu.cn/showproblem.php?pid=3065 Mean: 中文题,不解释. analyse: AC自动机的运用.这一题需要将模式串都存储下来,还有就是base的取值一定要弄清楚,由于这题的模式串都是大写字母所以我们可以通过剪枝来加速. Time complexity:o(n)+o(ml)  Source code: // Memory Time // 1347K 0MS // by : Snarl_js

hdu2896 病毒侵袭 AC自动机入门题 N(N &lt;= 500)个长度不大于200的模式串(保证所有的模式串都不相同), M(M &lt;= 1000)个长度不大于10000的待匹配串,问待匹配串中有哪几个模式串,

/** 题目:hdu2896 病毒侵袭 链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896 题意:N(N <= 500)个长度不大于200的模式串(保证所有的模式串都不相同), M(M <= 1000)个长度不大于10000的待匹配串,问待匹配串中有哪几个模式串, 题目保证每个待匹配串中最多有三个模式串. 思路:ac自动机做法,字符为可见字符,那么直接就是他们的ascii值作为每一个字符的标志.最多128: 由于不超过三个,所以找到3个就可以re