AC自动机

----多个模板的字符串匹配

字典树Trie加上失配边构成

插入操作:ac.insert(p[i],i);
构造失配函数:ac.getFail();
计算文本串T中每个模板串的匹配数:ac.find(T);

时间复杂度 O(n+km) (总长度)

以下是加过注释的LRJ模板:

struct ACauto
{
int ch[MAXN][];// 字典树,类似于前向星,ch[i][j]为当前编号为i的结点,下一个字符为j的所指向的编号。
int size;
int f[MAXN],last[MAXN],val[MAXN],cnt[MAXN];
//val用来在字典树中的模板串末尾处标记,标记为模板串的序号(从1开始)
//last后缀链接:结点J沿着失配指针往回走时,遇到的下一个单词尾结点。
//cnt用来统计配对数,每一个模板对应一个值,所以大小为模板数数量。只在print函数中使用 void init()//初始化
{
size=;//字典树中的节点数
memset(ch[],,sizeof(ch[]));//字典树
memset(cnt,,sizeof(cnt)); //用于统计配对数
} int idx(char c)//用于返回编号
{
return c-'a';
} void insert(char *s,int v)//将字符串s插入字典树中,其中v是字符串的编号,从1开始编号
{
int u=,len=strlen(s);
for (int i=;i<len;i++)
{
int c=idx(s[i]);
if (!ch[u][c])
{
memset(ch[size],,sizeof(ch[size]));
val[size]=;
ch[u][c]=size++;
}
u=ch[u][c];
}
val[u]=v;//在字符串末尾做出标记,标记为字符串的编号i
} void print(int j)//用于输出处理,
{
if (j)
{
cnt[val[j]]++;//成功配对数加1
print(last[j]);//继续沿后缀链接走检查是否和某个模板匹配。
}
} int getFail()//BFS构造失配函数
{
queue <int> q;
f[]=;
for (int c=;c<;c++)//把各个模板的第一个字符压入队列中
{
int u=ch[][c];
if (u)
{
f[u]=;
q.push(u);
last[u]=;
}
} while (!q.empty())
{
int r=q.front(); q.pop();
for (int c=;c<;c++)
{
int u=ch[r][c];
if (!u)
{
ch[r][c]=ch[f[r]][c];//如果节点不存在,直接链接到->失配边所指向的节点,这样能够化简计算
continue;
}
q.push(u);
f[u]=ch[f[r]][c];//构造当前节点的失配函数:如果失配,找到失配点的父亲节点r,父亲沿着失配边f[r]走向下一个节点即可。
last[u]=val[f[u]]?f[u]:last[f[u]];//构造后缀链接:如果沿失配指针走的节点是尾节点,就标记为失配指针指向的节点,
//否则标记为其后缀链接的值(类似于递归)。
}
}
} void find(char *T)//AC自动机主函数,在文本串T中寻找模板
{
int n=strlen(T);
int j=;
for (int i=;i<n;i++)
{
int c=idx(T[i]);//返回字符的编号
while(j&&!ch[j][c]) j=f[j];//如果字符不存在,即失配,就顺着失配边走,直到可以匹配
j=ch[j][c];//如果可以匹配,就走向下一个结点
if (val[j]) print(j);//如果j指向某个模板的尾部则输出
else if (last[j]) print(last[j]);//即使不是某个模板的尾部也要沿后缀链接走,检查是否为某个模板的尾部(如果存在的话)。
}
}
}ac;

AC自动机学习笔记的更多相关文章

  1. AC自动机学习笔记-2(Trie图&&last优化)

    我是连月更都做不到的蒟蒻博主QwQ 考虑到我太菜了,考完noip就要退役了,所以我决定还是把博客的倒数第二篇博客给写了,也算是填了一个坑吧.(最后一篇?当然是悲怆のnoip退役记啦QAQ) 所以我们今 ...

  2. AC自动机板子题/AC自动机学习笔记!

    想知道484每个萌新oier在最初知道AC自动机的时候都会理解为自动AC稽什么的,,,反正我记得我当初刚知道这个东西的时候,我以为是什么神仙东西,,,(好趴虽然确实是个对菜菜灵巧比较难理解的神仙知识点 ...

  3. [AC自动机][学习笔记]

    用途 AC自动机适用于一类用多个子串在模板串中匹配的字符串问题. 也就是说先给出一个模板串,然后给出一些子串.要求有多少个子串在这个模板串中出现过. KMP与trie树 其实AC自动机就是KMP与tr ...

  4. AC自动机学习笔记-1(怎么造一台AC自动机?)

    月更博主又来送温暖啦QwQ 今天我们学习的算法是AC自动机.AC自动机是解决字符串多模匹配问题的利器,而且代码也十分好打=w= 在这一篇博客里,我将讲解AC自动机是什么,以及怎么构建一个最朴素的AC自 ...

  5. AC 自动机学习笔记

    虽然 NOIp 原地爆炸了,目前进入 AFO 状态,但感觉省选还是要冲一把,所以现在又来开始颓字符串辣 首先先复习一个很早很早就学过但忘记的算法--自动 AC AC自动机. AC 自动机能够在 \(\ ...

  6. 【AC自动机】【字符串】【字典树】AC自动机 学习笔记

    blog:www.wjyyy.top     AC自动机是一种毒瘤的方便的多模式串匹配算法.基于字典树,用到了类似KMP的思维.     AC自动机与KMP不同的是,AC自动机可以同时匹配多个模式串, ...

  7. AC自动机学习

    今天包括这一周开始学习AC自动机了,有点晚,但我感觉努努力还来得及.4月份还得认认真真攻图论,加油! 为2个月后的邀请赛及省赛.东北赛做准备. 推荐AC自动机学习地址:http://www.cppbl ...

  8. 后缀自动机&回文自动机学习笔记

    在学了一天其实是边学边摆之后我终于大概$get$后缀自动机了,,,就很感动,于是时隔多年我终于决定再写篇学习笔记辽$QwQ$ $umm$和$FFT$学习笔记一样,这是一篇单纯的$gql$的知识总结博, ...

  9. AC自动机学习小结

    AC自动机 简要说明 \(AC\) 自动机,全称 \(Aho-Corasick\ automaton\) ,是一种有限状态自动机,应用于多模式串匹配.在 \(OI\) 中通常搭配 \(dp\) 食用. ...

随机推荐

  1. MS Writer Code Test

    #include<iostream> using namepspace std; int main() { cout<<"Hello World"<& ...

  2. Solr4.8.0源码分析(25)之SolrCloud的Split流程

    Solr4.8.0源码分析(25)之SolrCloud的Split流程(一) 题记:昨天有位网友问我SolrCloud的split的机制是如何的,这个还真不知道,所以今天抽空去看了Split的原理,大 ...

  3. JavaScript 项目构建工具 Grunt 实践:安装和创建项目框架

     Grunt 是一个基于任务的 JavaScript 项目命令行构建工具,运行于 Node.js 平台.Grunt 能够从模板快速创建项目,合并.压缩和校验 CSS & JS 文件,运行单元测 ...

  4. BZOJ 3196 二逼平衡树

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的 ...

  5. java security

    安全性是Java应用程序的非功能性需求的重要组成部分,如同其它的非功能性需求一样,安全性很容易被开发人员所忽略.当然,对于Java EE的开发人员来说,安全性的话题可能没那么陌生,用户认证和授权可能是 ...

  6. animate基础

    用JQUERY做动画是很方便的,已经看过大牛们做出不逊色于FLASH的各种效果. 其中的基本功就有animate这个方法的使用.于是,从零开始,训练基本功: <body> <div ...

  7. 6月A项目的总结

    对JS效果的要求有几点: 1.顶部导航栏鼠标经过动画. 2.Slider轮播图带有左右箭头,底部有缩略图,缩略图和大图都会自动播放. 3.右侧有个三个按钮的导航菜单,第一个按钮回到整个页面顶部,第二个 ...

  8. C++不能中断构造函数来拒绝产生对象(在构造和析构中抛出异常)

    这是我的感觉,具体需要研究一下- 找到一篇文章:在构造和析构中抛出异常 测试验证在类构造和析构中抛出异常, 是否会调用该类析构. 如果在一个类成员函数中抛异常, 可以进入该类的析构函数. /// @f ...

  9. Java实现Qt的SIGNAL-SLOT机制

    SIGNAL-SLOT是Qt的一大特色,使用起来十分方便.在传统的AWT和Swing编程中,我们都是为要在 监听的对象上添加Listener监听器.被监听对象中保存有Listener的列表,当相关事件 ...

  10. HDNOIP201206施工方案

    HDNOIP201206施工方案 难度级别:A: 运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 c国边防军在边境某处的阵地是由n个地堡组成的. ...