一、前言

以前一直没学AC自动机,主要是被名字吓到了,自动AC,这么强的名字肯定很难,学了后才发现,其实不难。

AC自动机并不是Acept automaton,而是Aho-Corasick automaton,A和C分别取自其发明者的姓名,有点巧。

那么,它是干什么的呢?

简而言之,是在文本串中寻找多个模板串的算法。

是不是类似于KMP算法?

KMP算法是在文本串中寻找一个模板串,那么,如果用KMP解决AC自动机的题,其时间复杂度是多少呢?

O(x*(n+m)),x是模板串的数量,n是文本串长度,m是模板串平均长度

显然,相较于暴力而言还算不错,但是当模板串过多时,这算法也不够优雅。

这时候就是AC自动机的闪亮登场了,其时间复杂度仅为O(n+x*m)。也就是说,我们仅需遍历一次文本串即可

二、思路

AC自动机 = KMP + Trie

KMP可以参考博文kmp算法讲解及其模板

Trie的话,本人暂时没写过博文,不过这部分也不算难,可自行百度。

至于AC自动机,感觉写起来有点麻烦,有点犯懒了,而且刚学,不算精通,暂时跳过。

三、代码

hdu 2222模板题

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e5+9; char s[maxn<<1];
int trie[maxn][26]; //字典树
int cntword[maxn]; //记录该单词出现次数
int fail[maxn]; //失败时的回溯指针
int cnt,n; int newNode(){//插入节点
cnt++;
for(int i = 0;i < 26;i++)
trie[cnt][i] = 0;
cntword[cnt] = fail[cnt] = 0;
return cnt;
} void init(){//初始化
cnt = -1;
cnt = newNode();
} void insertWords(){//单纯是Trie部分内容,建立字典树
int root = 0;
int len = strlen(s);
for(int i=0;i<len;i++){
int next = s[i] - 'a';
if(!trie[root][next])
trie[root][next] = newNode();
root = trie[root][next];
}
cntword[root]++; //当前节点单词数+1
}
void getFail(){
queue <int>q;
for(int i=0;i<26;i++){ //将第二层所有出现了的字母扔进队列
if(trie[0][i]){
fail[trie[0][i]] = 0;
q.push(trie[0][i]);
}
} //fail[now] ->当前节点now的失败指针指向的地方
////tire[now][i] -> 下一个字母为i+'a'的节点的下标为tire[now][i]
while(!q.empty()){
int now = q.front();
q.pop(); for(int i=0;i<26;i++){ //查询26个字母
if(trie[now][i]){
//如果有这个子节点为字母i+'a',则
//让这个节点的失败指针指向(((他父亲节点)的失败指针所指向的那个节点)的下一个节点)
//有点绕,为了方便理解特意加了括号 fail[trie[now][i]] = trie[fail[now]][i];
q.push(trie[now][i]);
}
else//否则就让当前节点的这个子节点
//指向当前节点fail指针的这个子节点
trie[now][i] = trie[fail[now]][i];
}
}
} int query(){
int now = 0,ans = 0;
int len = strlen(s);
for(int i=0;i<len;i++){ //遍历文本串
now = trie[now][s[i]-'a']; //从s[i]点开始寻找
for(int j=now;j && cntword[j]!=-1;j=fail[j]){
//一直向下寻找,直到匹配失败(失败指针指向根或者当前节点已找过).
ans += cntword[j];
cntword[j] = -1; //将遍历国后的节点标记,防止重复计算
}
}
return ans;
} int main() {
int t;
cin >> t;
while(t--){
init();
cin >> n;
for(int i=0;i<n;i++){//插入模板串
scanf("%s",s);
insertWords();
}
fail[0] = 0;
getFail();
scanf("%s",s);
cout << query() << endl;
}
return 0;
}

四、参考资料

https://blog.csdn.net/bestsort/article/details/82947639

(代码参考于此,由于hdu2222有点卡时间,所以有所修改)

字符串——AC自动机的更多相关文章

  1. 模板—字符串—AC自动机(多模式串,单文本串)

    模板—字符串—AC自动机(多模式串,单文本串) Code: #include <queue> #include <cstdio> #include <cstring> ...

  2. [coci2012]覆盖字符串 AC自动机

    给出一个长度为N的小写字母串,现在Mirko有M个若干长度为Li字符串.现在Mirko要用这M个字符串去覆盖给出的那个字符串的.覆盖时,必须保证:1.Mirko的字符串不能拆开,旋转:2.Mirko的 ...

  3. 【bzoj1030】: [JSOI2007]文本生成器 字符串-AC自动机-DP

    [bzoj1030]: [JSOI2007]文本生成器 首先把匹配任意一个的个数的问题转化为总个数-没有一个匹配的个数 先构造AC自动机,然后枚举每一位的字母以及在自动机上的位置 f[i][j]为第i ...

  4. 【bzoj3172】: [Tjoi2013]单词 字符串-AC自动机

    [bzoj3172]: [Tjoi2013]单词 先用所有单词构造一个AC自动机 题目要求的是每个单词在这个AC自动机里匹配到的次数 每次insert一个单词的时候把路径上的cnt++ 那么点p-&g ...

  5. JZYZOJ1369 [coci2012]覆盖字符串 AC自动机

    http://172.20.6.3/Problem_Show.asp?id=1369 trie树如果不优化就这么往里面放这么多单词肯定超空间+超时,所以需要去掉无用的字符串(不属于原字符串的),但是一 ...

  6. 【bzoj2434】: [Noi2011]阿狸的打字机 字符串-AC自动机-BIT

    [bzoj2434]: [Noi2011]阿狸的打字机 x串在y串上的匹配次数就是y在自动机所有节点上能够通过fail走到x最后一个节点的个数 (就是y串任意一个前缀的后缀能匹配到x的个数)和[bzo ...

  7. AC自动机相关Fail树和Trie图相关基础知识

    装载自55242字符串AC自动机专栏 fail树 定义 把所有fail指针逆向,这样就得到了一棵树 (因为每个节点的出度都为1,所以逆向后每个节点入度为1,所以得到的是一棵树) 还账- 有了这个东西, ...

  8. 「kuangbin带你飞」专题十七 AC自动机

    layout: post title: 「kuangbin带你飞」专题十七 AC自动机 author: "luowentaoaa" catalog: true tags: - ku ...

  9. 字符串处理-AC自动机

    估计在OJ上刷过题的都会对AC自动机这个名词很感兴趣,同样,记得去年ACM暑期集训的时候,在最后讲到字符串部分,听说了这个算法的名字之后就对于它心向往之,AC正好是Accept的简称,字面意义上的理解 ...

随机推荐

  1. stm32之HAL串口中断的callback流程图

  2. ESP8266乐鑫版本的(支持云端升级 (Boot 模式)烧写方法,(V1.5.4官方介绍如下)(BOOT模式)

    硬件平台: nodeMCU devkit核心板,带ch340g,应该是仿造的,官方是cp2102驱动,安信可科技有连接https://wiki.ai-thinker.com/esp8266/board ...

  3. nginx.conf文件的使用

    默认配置语法 全局---服务级别的配置 user 设置nginx服务的系统使用用户,基本上不用动 worker_processes 工作进程数---跟nginx多worker有关,增大连接数的并发处理 ...

  4. 一些C++编码规范

    1.成员变量是引用类型,头文件只需向前声明对应类,不需包含类头文件,在实现文件中需要包含: 2.头文件声明变量和函数按照pulic.protected.private顺序: 3.成员变量声明,加 &q ...

  5. [python](Docker SDK)上传镜像到私有仓库(tls、身份认证)

    (Docker SDK)上传镜像到私有仓库(tls.身份认证) API:https://docker-py.readthedocs.io/en/stable/ 环境:python:3.7.3 配置参数 ...

  6. NOI2019 游记

    day-1 广二真好看QAQ (要是我也能在这里读书就好了) 提供的餐饮好评QAQ 发现室友是雅礼集训时候的室友,衡水小姐姐zyn. 但是寝室没有网没有信号没有桌子真的不良心啊...... 发现小卖部 ...

  7. TensorFlow使用记录 (九): 模型保存与恢复

    模型文件 tensorflow 训练保存的模型注意包含两个部分:网络结构和参数值. .meta .meta 文件以 “protocol buffer”格式保存了整个模型的结构图,模型上定义的操作等信息 ...

  8. 【集训队作业2018】小Z的礼物

    小水题.题意就是不断随机放一个 \(1 \times 2\) 骨牌,然后取走里面的东西.求期望多少次取走所有的东西.然后有一维很小. 首先显然 minmax 容斥,将最后取走转化为钦定一些物品,求第一 ...

  9. BZOJ 2959 长跑 (LCT、并查集)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2959 题解 真是被这题搞得心态大崩--调了7个小时--然而并查集都能写成\(O(n^2) ...

  10. [c++] C++中public、protected、private的区别

    转:https://blog.csdn.net/vanturman/article/details/79393317 第一: private,public,protected的访问范围: privat ...