当前位置: 首页 > news >正文

贴合《算法竞赛入门经典训练指南》AC 自动机完整代码

一、程序

包含字典树构建、fail 指针 BFS、模式匹配 Find、递归打印匹配结果 Print全流程。

#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;const int MAXN = 10000 + 10;  // 字典树最大节点数,按需调整
const int MAXC = 26;          // 字符集:小写字母a-z// AC自动机节点结构
struct AhoCorasick {int ch[MAXN][MAXC];       // 字典树:ch[u][c]表示u节点走c字符到的节点int fail[MAXN];           // fail指针vector<int> val[MAXN];    // val[u]:存储以u节点结尾的模式串编号(多模式匹配)int sz;                   // 节点总数,初始为0// 初始化AC自动机void init() {sz = 0;memset(ch[0], 0, sizeof(ch[0]));val[0].clear();}// 插入模式串s,id为模式串编号(用于区分匹配到的是哪个模式串)void insert(const char *s, int id) {int u = 0;for (int i = 0; s[i]; i++) {int c = s[i] - 'a';if (!ch[u][c]) {sz++;memset(ch[sz], 0, sizeof(ch[sz]));val[sz].clear();ch[u][c] = sz;}u = ch[u][c];}val[u].push_back(id);  // 该节点记录模式串id}// BFS构建fail指针void build() {queue<int> q;fail[0] = 0;for (int c = 0; c < MAXC; c++) {int v = ch[0][c];if (v) {fail[v] = 0;q.push(v);}}while (!q.empty()) {int u = q.front();q.pop();for (int c = 0; c < MAXC; c++) {int v = ch[u][c];if (v) {// 计算fail[v]:回溯u的fail指针,找到能走c的节点int f = fail[u];while (f && !ch[f][c]) f = fail[f];fail[v] = ch[f][c];q.push(v);} else {// 路径压缩:直接指向fail后的节点,优化查询速度ch[u][c] = ch[fail[u]][c];}}}}// 递归打印:以j节点结尾的所有匹配模式串(配合Find函数,i是文本串当前结束位置)// 书中Print(i,j)是解释性写法,实际仅需j,i在调用时传入计算位置void Print(int i, int j, const vector<char*>& patterns) {if (j == 0) return;  // 根节点,无匹配// 打印当前节点的所有匹配结果:i是文本串结束位置,patterns[id]是模式串内容for (int id : val[j]) {int len = strlen(patterns[id]);printf("匹配到模式串:%s,结束位置:%d,起始位置:%d\n", patterns[id], i, i - len + 1);}// 递归回溯fail指针,打印所有间接匹配(AC自动机核心:fail链匹配)Print(i, fail[j], patterns);}// 核心匹配函数Find:在文本串T中找所有模式串,patterns是模式串数组void Find(const char *T, const vector<char*>& patterns) {int u = 0;for (int i = 0; T[i]; i++) {  // i是文本串当前位置(从0开始)int c = T[i] - 'a';u = ch[u][c];  // 按字典树+路径压缩走if (val[u].size() || fail[u]) {  // 有匹配结果,调用PrintPrint(i + 1, u, patterns);  // 文本串位置转成从1开始,更符合阅读习惯}}}
} ac;// 测试主函数
int main() {// 步骤1:初始化AC自动机ac.init();// 步骤2:插入模式串(可自定义,示例:3个模式串)vector<char*> patterns;  // 存储模式串,与id一一对应char s1[] = "she";char s2[] = "he";char s3[] = "his";patterns.push_back(s1);patterns.push_back(s2);patterns.push_back(s3);ac.insert(s1, 0);ac.insert(s2, 1);ac.insert(s3, 2);// 步骤3:构建fail指针ac.build();// 步骤4:文本串匹配char T[] = "hishers";  // 测试文本串printf("文本串:%s\n", T);printf("匹配结果:\n");ac.Find(T, patterns);return 0;
}

二、细节说明

1、Print 函数参数:书中Print(i,j)是读者理解用的简化写法,实际代码中Print需要i(文本串结束位置)+j(AC 节点)+patterns(模式串数组),其中i仅用于计算并打印匹配的起始 / 结束位置,j是核心的 AC 节点,用于递归遍历fail链找所有匹配。
2、与书中的对应关系:

  • 书中ch数组 → 代码中ch[MAXN][MAXC](字典树核心);
  • 书中fail数组 → 代码中fail[MAXN](BFS 构建);
  • 书中val数组 → 代码中val[MAXN](存储模式串编号,支持多模式匹配);
  • 书中Find函数逻辑完全一致 → 文本串遍历 + 节点跳转 +Print调用;
  • 书中Print递归逻辑 → 代码中严格实现节点 j 的直接匹配 + fail 链的间接匹配。

3、路径压缩优化:代码中ch[u][c] = ch[fail[u]][c]是书中的优化点,避免每次匹配都回溯fail指针,提升运行效率。

三、编译运行结果(示例)

上述测试代码的运行输出(文本串hishers,模式串she/he/his):

文本串:hishers
匹配结果:
匹配到模式串:his,结束位置:3,起始位置:1
匹配到模式串:he,结束位置:5,起始位置:4
匹配到模式串:she,结束位置:6,起始位置:4
匹配到模式串:he,结束位置:6,起始位置:5

四、自定义修改说明

1、字符集调整:若需支持大写字母 / 数字,修改MAXC和c = s[i] - 'a'的偏移量即可;
2、模式串数量:直接在main函数中添加insert调用,patterns数组同步添加即可;
3、文本串输入:可将固定文本串改为scanf/gets读取外部输入,适配算法竞赛场景。

http://www.jsqmd.com/news/349274/

相关文章:

  • 2026年热门的盘龙区心理咨询,昆明心理咨询,本地心理咨询公司行业热门推荐 - 品牌鉴赏师
  • 2026高价回收设备推荐:深圳市罗湖区至诚电脑回收中心,全品类覆盖,服务超万家客户 - 品牌推荐官
  • 2026年上海疤痕医院推荐:长期疗效与成本效益评测,解决增生与凹陷双重痛点 - 品牌推荐
  • 分析电子元器件回收公司口碑,深圳满芯微等推荐哪家 - 工业设备
  • 2026年南京比较好的安全环保管家技术服务,职业卫生“三同时”技术服务,安全台账资料编制技术服务公司采购优选榜单 - 品牌鉴赏师
  • 不同疤痕类型该如何治疗?2026年上海疤痕医院推荐与评价,针对挛缩与平整度修复场景 - 品牌推荐
  • 好写作AI:从草稿到成稿的AI加速器——把论文写作从“马拉松”变成“接力赛”
  • 电子元器件回收服务靠谱吗,上海优质品牌排名 - 工业设备
  • 2026最新成都流水线厂家权威排行榜|四川流水线厂家、输送设备、自动化设备、工业自动化装备、生产线成套设备、工厂物流成套设备、车间工位设备排名 - 品牌智鉴榜
  • 加油卡闲置无处用?中石油加油卡回收变现最快捷方案 - 团团收购物卡回收
  • 盘点龙膜授权企业排名,青岛专业汽车贴膜店哪家性价比高 - 工业品牌热点
  • 好写作AI:跨学科论文的AI写作策略——你的“学术翻译官”与“思维脚手架”
  • 课程论文写哭?虎贲等考AI 3小时搞定90分作业,老师都夸专业度超标
  • 聊聊可以上门的回收电子元器件平台,推荐品牌有哪些 - 工业品牌热点
  • 基于PLC的模具加工控制系统,采用博途软件编写,提供画面,接线图,IO分配表。 实现功能(详见...
  • 「真实分享」探索AI创作的秘密:为什么API平台是小说开发者的必备工具?
  • 文档数据库替换方案是什么?KES兼容MongoDB的原理与应用场景
  • 中石油加油卡变现靠谱吗?安全回收平台推荐 - 团团收购物卡回收
  • 基于SpringBoot的汽车维修管理系统设计与实现(毕业论文)
  • UE5 多线程(7-2):AsyncTask
  • SSO单点登录与OAuth2.0:从原理到实践的全面解析
  • C#: 告别繁琐!轻松移除Word文档中的文本与图片水印
  • 时序数据库与等保三级数据库:2026通俗扫盲指南
  • 3D重建技术全景指南
  • 3.2 查询缓存优化:如何正确使用和优化MySQL查询缓存
  • 2026年兰州男科医院推荐:2026年技术趋势横向对比排名,针对费用透明与疗效痛点 - 品牌推荐
  • 期货市流动性危机
  • 对贵金属市场的
  • 从回调函数到Promise
  • 3.3 索引优化实战:让你的查询速度提升10倍的秘密武器