C++ AC自动机算法

本文介绍了AC自动机算法,它是基于Trie树的多模匹配算法,适用于大量字符串的统计和排序。文章详细讲解了AC自动机的构造过程,包括建树、预处理失配指针nex和匹配,并提供了算法实现。此外,推荐了两个洛谷平台的AC自动机例题供读者实践。

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

目录:

AC自动机简介

如何构造 AC自动机

算法实现

        1、建树

        2、预处理失配指针 nex

        3、匹配

AC自动机例题推荐


AC自动机简介:

        正所谓 AC自动机,就是能自动 AC 的算法。

        AC自动机全称:Aho-Corasick automaton,该算法于1975年产生于贝尔实验室,是著名的多模匹配算法。

        实际上,AC自动机就是在 Trie 树上实现KMP,来达到完成多模式串匹配的效果。

        要学会AC自动机,先得有字典树 Trie 和 KMP模式匹配算法的基础知识。

        典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。

        给大家一张 AC自动机 的图片:

如何构造 AC自动机:

        构造一个 AC自动机并用于匹配,主要有三个步骤:

                1、建树:将所有模式串构成一颗 Trie树。

                2、预处理失配指针 nex:对 Trie树的所有节点构造失配指针。

                3、匹配:利用 Trie树和失配指针对主串进行匹配。

算法实现:

        1、建树:

                就是将所有的主串 S 依次插入,构成一颗 Trie树(还不会 Trie树的OIers可以去C++        Trie树算法的相关知识看看)。

        2、预处理失配指针 nex:  

                先详细讲一下什么是失配指针:设 root(Trie树的根节点) 到 i

### AC自动机算法概述 AC自动机是一种用于多模式串匹配的经典算法,其核心思想是通过构建一个有限状态自动机来高效地查找多个模式串在一个文本中的位置。它由 Alfred V. Aho 和 Margaret J. Corasick 于1975年在贝尔实验室提出[^1]。 #### 构建过程 AC自动机的核心在于字典树(Trie)结构的扩展。以下是主要组成部分: 1. **字典树的建立** 字典树是一个前缀树数据结构,能够有效地存储一组字符串集合。对于给定的一组模式串,可以将其插入到字典树中以便后续处理。 2. **失败指针的构造** 失败指针的作用是在当前路径无法继续匹配的情况下跳转至可能的最大公共前后缀节点。这一部分通常利用广度优先搜索(BFS)完成,按照层次遍历的方式逐一为每个节点设置失败指针[^2]。 3. **匹配阶段** 在完成了上述准备工作之后,可以通过一次线性扫描输入文本并借助已构建的状态转移机制快速定位所有出现的目标子串及其起始位置。 #### 实现代码示例 下面展示了一个简单的 C++ 版本实现: ```cpp #include <bits/stdc++.h> using namespace std; const int MAXN = 1000; // 节点数上限 struct Node { int next[26]; // 子节点数组 int fail; // 失败指针 bool isEnd; // 是否为某个单词结尾标志位 } trie[MAXN]; int root, cnt; void init() { // 初始化函数 root = cnt = 0; memset(trie[root].next, -1, sizeof(trie[root].next)); } // 插入操作 void insert(string s){ int p = root; for(char c : s){ if (trie[p].next[c-'a'] == -1){ trie[cnt+1].fail = -1; memset(trie[cnt+1].next,-1,sizeof(trie[cnt+1].next)); trie[p].next[c-'a']= ++cnt;} p=trie[p].next[c-'a']; } trie[p].isEnd=true; } queue<int> q; void build(){ for(int i=0;i<26;i++)if(trie[root].next[i]!=-1){q.push(trie[root].next[i]);} while(!q.empty()){ int r=q.front();q.pop(); for(int i=0;i<26;i++){ if(trie[r].next[i]==-1)continue; int u=trie[r].next[i]; int v=trie[r].fail; while(v!=-1&&trie[v].next[i]==-1)v=trie[v].fail; if(v==-1)trie[u].fail=root; else trie[u].fail=trie[v].next[i]; q.push(u); } } } vector<string> res; string text; void query(int idx,int node){ if(idx==text.size())return ; char c=text[idx]-'a'; while(node !=root && trie[node].next[c]==-1)node=trie[node].fail; if(trie[node].next[c]!=-1)node=trie[node].next[c]; if(trie[node].isEnd)res.emplace_back(text.substr(0,idx+1)); query(idx+1,node); } int main(){ ios::sync_with_stdio(false);cin.tie(NULL); string pattern[]={"he","she","his","her"}; init(); for(auto &s:pattern)insert(s); build(); cin>>text; res.clear(); query(0,root); cout<<"Matched patterns:\n"; for(auto&s:res)cout<<s<<"\n"; return 0; } ``` 此程序展示了如何使用 AC 自动机进行基本的多模式串匹配任务,并打印出找到的所有匹配项。 #### 应用场景 由于其实效性和灵活性,AC 自动机广泛应用于各种领域之中,例如但不限于以下几个方面: - 文本编辑器中的关键字高亮显示功能; - 垃圾邮件过滤系统里识别黑名单词汇列表; - 生物信息学研究基因序列分析过程中寻找特定片段的存在情况等。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值