AC自动机算法简介(洛谷P3808)

AC自动机算法常用于高效解决查找多个单词在文本中出现次数的问题,它基于Trie树和KMP算法,通过预处理失配指针实现快速匹配。在洛谷P3808等题目中,该算法能显著提升效率。理解AC自动机需要掌握Trie树和KMP的基础知识。在构建Trie树和处理失配指针时,需要特别注意队列扩展。查询阶段通过扫描文本与Trie树匹配,记录出现的字符串数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法用途

一个常见的例子就是给出n个单词,再给出一段包含m个字符的文章,让你找出有多少个单词在文章里出现过。如果直接跑n遍KMP的话时间复杂度会较高(O(nm)),这时AC自动机算法便应运而生。

算法先决条件

要学会AC自动机,首先需要掌握Trie树和KMP算法。

KMP算法入门 Trie树入门

算法思想

把所有的模板串存到Trie中,预处理出每个节点的失配指针(和KMP中的next数组很像),在查询时实现快速跳转。(其实就是在Trie上KMP)

算法要点

洛谷P3808为例,完整代码请见模板1

构造Trie树

这个就是Trie树的插入操作,根本没有任何区别啊!
根据题目所求可以适当修改所需记录的量。

void nsrt(char s[]){
    int node=0,len=strlen(s);//一定要先算好s的长度,不然会T掉的(别问我怎么知道的)
    for (int i=0;i<len;i++){
        int x=s[i]-'a';
        if (!a[node][x])//如果没有这个儿子
            a[node][x]=++k;//给这个儿子编号
        node=a[node][x];//继续循环
    }
    f[node]++;//该字符串以这个字符为结尾
}

失配指针

在处理失配指针时,要使用队列扩展(想想为什么)。其他具体见代码注释

void asknxt(){
    queue<int>que;//队列
    //先把root的子节点加入队列中
    for (int i=0;i<26;i++)
        if (a[0][i]){
            que.push(a[0][i]);
            nxt[a[0][i]]=0;
        }
    while (!que.empty()){
        int x=que.front();
        que.pop();
        int node=nxt[x];//node为x的失配指针所指向的节点
        //枚举x的所有子节点
        for (int i=0;i<26;i++)
            if (a[x][i]){
  
  //如果存在该节点
         
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值