AC自动机

AC自动机

         直接学AC自动机比较难理解,强烈建议先学完KMP和字典树并进行一定的练习后,对于失配指针和字典树构造有一定理解后再来学AC自动机的内容。有关AC自动机的详细介绍可见刘汝佳的《算法竞赛入门经典训练指南》P214.

给你一个字典(包含n个不重复的单词),然后给你一串连续的字符串文本(长为len),问你该文本里面的哪些位置正好出现了字典中的某一个或某几个单词?输出这些位置以及出现的单词。

         这个问题可以用n个单词的n次KMP算法来做(效率为O(n*len*单词平均长度)),也可以用1个字典树去匹配文本串的每个字母位置来做(效率为O(len*每次字典树遍历的平均深度))。上面两种解法效率都不高,如果用AC自动机来解决的话,效率将为线性O(len)时间复杂度。(上述3种时间效率并未把构建KMP,字典树以及AC自动机的时间算上)

         KMP算法专门解决长文本的单模板匹配问题,字典树专门解决单个单词(短文本)多模板匹配问题。而AC自动机解决的是长文本的多模板匹配问题。且AC自动机不但时间上具有优势,空间上也颇具优势。

模板代码如下:

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxnode=11000;
const int sigma_size=26;
struct AC_Automata
{
    int ch[maxnode][sigma_size];
    int val[maxnode];   // 每个字符串的结尾结点都有一个非0的val
    int f[maxnode];     // fail函数
    int last[maxnode];  // last[i]=j表j节点表示的单词是i节点单词的后缀,且j节点是单词节点
    int sz;

    //初始化0号根节点的相关信息
    void init()
    {
        sz=1;
        memset(ch[0],0,sizeof(ch[0]));
        val[0]=0;
    }

    //insert负责构造ch与val数组
    //插入字符串,v必须非0表示一个单词节点
    void insert(char *s,int v)
    {
        int n=strlen(s),u=0;
        for(int i=0; i<n; i++)
        {
            int id=s[i]-'a';
            if(ch[u][id]==0)
            {
                ch[u][id]=sz;
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz++]=0;
            }
            u=ch[u][id];
        }
        val[u]=v;
    }

    //getFail函数负责构造f和last数组
    void getFail()
    {
        queue<int> q;
        last[0]=f[0]=0;
        for(int i=0; i<sigma_size; i++)
        {
            int u=ch[0][i];
            if(u)
            {
                f[u]=last[u]=0;
                q.push(u);
            }
        }

        while(!q.empty())// 按BFS顺序计算fail
        {
            int r=q.front(); q.pop();
            for(int i=0; i<sigma_size; i++)
            {
                int u=ch[r][i];
                if(u==0)continue;
                q.push(u);

                int v=f[r];
                while(v && ch[v][i]==0) v=f[v];
                f[u]= ch[v][i];
                last[u] =  val[f[u]]?f[u]:last[f[u]];
            }
        }
    }

    //递归打印与结点i后缀相同的前缀节点编号
    //进入此函数前需保证val[i]>0
    void print(int i)
    {
        if(i)
        {
            printf("%d\n",i);
            print(last[i]);
        }
    }

    // 在s中找出 出现了哪几个模板单词
    void find(char *s)
    {
        int n=strlen(s),j=0;
        for(int i=0; i<n; i++)
        {
            int id=s[i]-'a';
            while(j && ch[j][id]==0) j=f[j];
            j=ch[j][id];
            if(val[j]) print(j);
            else if(last[j]) print(last[j]);
        }
    }

};
AC_Automata ac;

AC自动机的基本应用

UVA 1449 Dominating Patterns(AC自动机):注意输入中有重复单词输入的情况。解题报告!

HDU 2222 Keywords Search(AC自动机):给你一个文本和多个单词,问你出现了多少个单词。注意单词可能会重复。解题报告

HDU 2896 病毒侵袭(AC自动机):AC自动机基本应用。解题报告!

HDU 3065 病毒侵袭持续中(AC自动机):AC自动机基本应用。解题报告

ZOJ 3430 Detect the Virus(AC自动机+字符串转换):本题麻烦在于匹配AC自动机之前需要先把64位编码转换为字符串。解题报告

ZOJ 3228 Searching the String(AC自动机):相同模板串不可重叠如何求最大出现次数?解题报告

 

AC自动机+DP

UVA 11468 Substring(AC自动机+概率DP):需要用改造后的AC自动机且注意概率dp的实现。解题报告!

POJ 2778 DNA Sequence(AC自动机+矩阵幂DP):需要先用DP求出递推公式,然后找出递推矩阵,本题就是一个矩阵幂运算的题。解题报告

HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵幂):POJ2778的加强版。解题报告

POJ 1625 Censored!(AC自动机+DP):类似POJ2778,不过不需要矩阵幂。解题报告!

HDU 2825 Wireless Password(AC自动机+状态压缩DP):依然是生成字符串,但是这次要正好包含K个不同的模板单词。解题报告

HDU 2296 Ring(AC自动机+DP): 注意match数组的值。解题报告!

HDU 2457 DNA repair(AC自动机+DP):很巧妙的DP定义。解题报告!

HDU 3341 Lost's revenge(AC自动机+DP):另类的状态压缩DP题,以后记得这么压缩状态。解题报告!

 

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python AC自动机是一个用于字符串匹配的算法,它可以高效地在一段文本中查找多个预定义的模式。它的实现可以使用多种库,其中包括ac自动机python和ahocorasick-python。 ac自动机python是一个对标准的ac自动机算法进行了完善和优化的实现,适用于主流的Python发行版,包括Python2和Python3。它提供了更准确的结果,并且可以通过pip进行安装,具体的安装方可以参考官方文档或者使用pip install命令进行安装。 ahocorasick-python是另一个实现AC自动机的库,它也可以用于Python2和Python3。你可以通过官方网站或者GitHub源码获取更多关于该库的信息和安装指南。 对于AC自动机的使用,一个常见的例子是在一段包含m个字符的文章中查找n个单词出现的次数。要了解AC自动机,需要有关于模式树(字典树)Trie和KMP模式匹配算法的基础知识。AC自动机算法包括三个步骤:构造一棵Trie树,构造失败指针和模式匹配过程。在构造好AC自动机后,可以使用它来快速地在文本中查找预定义的模式,并统计它们的出现次数。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [ahocorasick-python:AC自动机python的实现,并进行了优化。 主要修复了 查询不准确的问题](https://download.csdn.net/download/weixin_42122986/18825869)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Python实现多模匹配——AC自动机](https://blog.csdn.net/zichen_ziqi/article/details/104246446)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值