【模版】(旧)AC自动机
AC自动机
(注:此博不是讲解,只是备忘用的)
多模式串匹配的好东西~
以trie树为保存字符串的载体,在树上建立失配边来进行模式串间的转移,以达到快速匹配的目的。
以 HDU:2222 Keywords Search 为例:
(但有些部分代码设计不太合理,可根据题微调)
(此处采用了建trie图的思想加速,但实际还可以用last数组再度加速)
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #define MSZ (1000000) #define SZ (50) #define SGSZ (26) using namespace std;struct TRIE {char cc;int fail, last;int get, cnt;int next[SGSZ]; };int cTr; TRIE Tr[MSZ]; // * those are my magic #define np(p, id) (Tr[p].next[id]) #define fp(p) (Tr[p].fail) #define lp(p) (Tr[p].last) #define ct(p) (Tr[p].cnt) #define gt(p) (Tr[p].get)int T, N;// * get a char's index inline int index(char cc) {return cc - 'a'; }inline char opdex(int id) {return id + 'a'; }// * clear the Trie void ClearTr() {for (int i = 0; i <= cTr; i++)Tr[i] = (TRIE){0, 0, 0, 0, 0, 0};return; }// * add a point into Trie int AddPTr(int id) {Tr[++cTr].cc = opdex(id);return cTr; }// * add a string into Trie void AddSTr(char s[]) {int p = 0, l = strlen(s);for (int i = 0; i < l; i++){int id = index(s[i]);if (!np(p, id))np(p, id) = AddPTr(id);p = np(p, id); // * Magic part , careful ! }ct(p)++, lp(p) = p;return; }void FailAc() {queue<int> Q;for (int id = 0; id < SGSZ; id++)if (np(0, id))Q.push(np(0, id));while (!Q.empty()){int p = Q.front();Q.pop();for (int id = 0; id < SGSZ; id++){int tp = fp(p);while (tp && !np(tp, id))tp = fp(tp);if (np(p, id)){Q.push(np(p, id));fp(np(p, id)) = np(tp, id);lp(np(p, id)) = ct(np(tp, id)) ? np(tp, id) : lp(np(tp, id));}elsenp(p, id) = np(tp, id);}}return; }int FindAc(char ms[]) {int p = 0, l = strlen(ms), sum = 0;for (int i = 0; i < l; i++){int id = index(ms[i]);p = np(p, id);int tp = p;while (tp){if (gt(tp))break;gt(tp) = 1;if (ct(tp))sum += ct(tp);tp = lp(tp);}}return sum; }int main() {char s[SZ], ms[MSZ];scanf("%d", &T);while (T--){scanf("%d", &N);ClearTr();for (int i = 1; i <= N; i++){scanf("%s", s);AddSTr(s);}FailAc();scanf("%s", ms);printf("%d", FindAc(ms));}return 0; }
寻找失配边的fail函数:
...
void FailAc() {queue<int> Q;for (int id = 0; id < SGSZ; id++)if (np(0, id))Q.push(np(0, id));while (!Q.empty()){int p = Q.front();Q.pop();for (int id = 0; id < SGSZ; id++){int tp = fp(p);while (tp && !np(tp, id))tp = fp(tp);if (np(p, id)){Q.push(np(p, id));fp(np(p, id)) = np(tp, id);lp(np(p, id)) = ct(np(tp, id)) ? np(tp, id) : lp(np(tp, id));}elsenp(p, id) = np(tp, id);}}return; }
寻找匹配串数量的find函数:
包括fail函数,一定要记住一些明显的优化,比如trie图转化,get标记,last记录上个单词节点。
int FindAc(char ms[]) {int p = 0, l = strlen(ms), sum = 0;for (int i = 0; i < l; i++){int id = index(ms[i]);p = np(p, id);int tp = p;while (tp){if (gt(tp))break;gt(tp) = 1;if (ct(tp))sum += ct(tp);tp = lp(tp);}}return sum; }
清空和加入节点:(以下是Tire树操作)
这是一种很蠢的写法,实际中节点可以直接删除(如用memset清空,不过可能会卡)。
// * add a point into Trie int AddPTr(int id) {Tr[++cTr].cc = opdex(id);return cTr; }// * add a string into Trie void AddSTr(char s[]) {int p = 0, l = strlen(s);for (int i = 0; i < l; i++){int id = index(s[i]);if (!np(p, id))np(p, id) = AddPTr(id);p = np(p, id); // * Magic part , careful ! }ct(p)++, lp(p) = p;return; }
将字符转化成编号和反转化的函数:
这是为那些写trie树却不会指针的同学们准备的,将每个字符转化成唯一对应的下标。
// * get a char's index inline int index(char cc) {return cc - 'a'; }inline char opdex(int id) {return id + 'a'; }
宏黑魔法++。
转载于:https://www.cnblogs.com/Ztraveler/p/6933512.html
【模版】(旧)AC自动机相关推荐
- HDU2896(AC自动机模版题)
AC自动机模版题: 方法一:超时 #include<iostream> #include<algorithm> #include<cstring> #include ...
- hdu 2222 AC 自动机 模版(数组实现)
AC 自动机 模版 原文匹配查找时讲错了,其他都挺好(原文博主知错懒得改 t个样例,n个单词,一个文本串,求文本串中单词出现的次数. 若给出单词ab,ab 文本ab,匹配数为2 若给出 n个不重复的单 ...
- HDU2222(AC自动机模版题)
AC自动机是Trie树和KMP的结合物,但是其实KMP在这里体现了思想,而Trie树才是最重要的,要想学懂AC自动机,学习Trie树是必须的,这些是自己在学习AC自动机的个人看法,我也是在网上学习了大 ...
- 【HDU2896】病毒侵袭——ac自动机
网上很多代码都略显繁琐,看了一下yy dalao的代码感觉很好,但他懒得打题解(好吧我也是 以0为根节点的话,我把yy的一段代码删了改用fail[c]=x==0?0:ch[fail[x]][i];来实 ...
- hdu 2222 Keywords Search(ac自动机)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:给你一系列子串,再给你一个主串问你主串一共有几个匹配子串 原来使用字典树写的但数据有点大T ...
- AC自动机——Uva 11468 子串
题目链接:http://vjudge.net/contest/142513#problem/A 题意:给出一些字符和各自对应的选择概率,随机选择L次后将得到一个长度为L的随机字符串S.给出K个模版串, ...
- 字符串处理 —— AC 自动机
[概述] KMP 算法用于解决长文本的单模板匹配问题,字典树用于解决单个单词(短文本)多模板匹配问题,而 AC 自动机用于解决的是长文本的多模板匹配问题,其是以 trie 树的结构为基础,结合 KMP ...
- 【距离GDOI:128天】【POJ2778】DNA Sequence(AC自动机+矩阵加速)
已经128天了?怎么觉得上次倒计时150天的日子还很近啊 ....好吧为了把AC自动机搞透我也是蛮拼的..把1030和这道题对比了无数遍...最终结论是...无视时间复杂度,1030可以用这种写法解. ...
- HiHocoder 1036 : Trie图 AC自动机
Trie图 先看一个问题:给一个很长很长的母串 长度为n,然后给m个小的模式串.求这m个模式串里边有多少个是母串的字串. 最先想到的是暴力O(n*m*len(m)) len(m)表示这m个模式串的平均 ...
- 数据结构与算法之美笔记——基础篇(下):图、字符串匹配算法(BF 算法和 RK 算法、BM 算法和 KMP 算法 、Trie 树和 AC 自动机)
图 如何存储微博.微信等社交网络中的好友关系?图.实际上,涉及图的算法有很多,也非常复杂,比如图的搜索.最短路径.最小生成树.二分图等等.我们今天聚焦在图存储这一方面,后面会分好几节来依次讲解图相关的 ...
最新文章
- java常见集合及其用途
- 【枚举】【SPFA】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem I. Iron and Coal
- 1500+ FPS!目前最快的CNN人脸检测算法开源
- 在C#中利用Keep-Alive处理Socket网络异常断开的方法
- 推荐 | 8 个 SpringBoot 精选项目
- 这些新技术你们都知道吗?成功收获美团,小米安卓offer
- 日期 java cal,日期系列教材 (三)- 如何使用Java的Calendar类
- 作者:​林旺群(1983-),男,博士,北京系统工程研究所助理研究员。
- VB 迅雷下载地址解密函数
- 抛弃jQuery 深入原生的JavaScript
- 转载 分布式协调技术 分布式锁
- JAVA电子书大礼包
- 临床试验数据管理系统
- cad沿线插入块 lisp_我有一组数有十几万个坐标点,如何利用lisp程序快速导入CAD中,并可以快速处理!...
- 心率检测实现报告(一)
- 【Python小工具】若干图片合并生成动态图(.gif)
- 在总账模块结账的时候提示总账和明细账对账不平结不了账
- iOS创建沙盒账号的步骤和注意事项
- 网站关键词优化该怎么做?
- 增值税发票二维码解析
热门文章
- php刷新显示不一样的语录,JavaScript_js每次Title显示不同的名言,每次都有不同的名言出来。 实 - phpStudy...
- vant 时间选择的用法
- ElasticSearch7.3学习(二十六)----搜索(Search)参数总结、结果跳跃(bouncing results)问题解析
- 学生党还是不当月光族舒服
- Sint at magni ducimus veniam dolores eaque volNobis harum mollitia nulla laboriosam dolore.uptatum.
- web服务器系统事件日志,web 服务器的系统事件日志
- 在java中类的标志是什么车_JAVA写一个汽车类,属性:品牌;车长;颜色;价格;方法:跑的方法...
- 元宇宙商标现在都怎么样了
- python 实现软件更新
- 什么是.bak文件?探索编程中的备份文件