华电北风吹
日期:2016-05-03

AC自动机是比较高效的多模式匹配算法。类似于KMP在模式串上的状态转移算法,AC自动机通过在trie树上建立状态转移,使得对匹配串遍历一遍就可以找到所有的模式串。
AC自动机一般有以下三步:首先,对所有的模式串建立trie树。然后,对trie树所有节点以它的最长后缀对应的前缀字符串作为它的失配指针,建立AC自动机。最后一步,对文本串在AC自动机上进行匹配。

题目链接:
http://hihocoder.com/problemset/problem/1036?sid=786758

参考代码:

#include <iostream>
#include <queue>
#include <string>
#include <string.h>
using namespace std;#define size 26struct node
{node *fail;          //失败指针node *next[size];    //Tire每个节点有26个子节点,分别对应26个英文字母int count;           //该节点是否为单词的末尾节点node(){fail = NULL;count = 0;memset(next, NULL, sizeof(next));}
};void Insert(node *root, string str)
{node *p = root;int i = 0, index;for (int i = 0; i < str.length(); i++){index = str[i] - 'a';if (p->next[index] == NULL)p->next[index] = new node();p = p->next[index];}p->count++;
}
void GetFail(node *root)
{int i;root->fail = NULL;queue<node*> q;q.push(root);while (q.empty() == false){node *temp = q.front();q.pop();node *p = NULL;for (i = 0; i<size; i++){if (temp->next[i] != NULL){if (temp == root)temp->next[i]->fail = root;else{p = temp->fail;while (p != NULL){if (p->next[i] != NULL){temp->next[i]->fail = p->next[i];break;}p = p->fail;}if (p == NULL)temp->next[i]->fail = root;}q.push(temp->next[i]);}}}
}
bool Query(node *root, string str)
{int cnt = 0, index;node *p = root;for (int i = 0; i < str.length(); i++){index = str[i] - 'a';while (p->next[index] == NULL && p != root)p = p->fail;p = p->next[index];p = (p == NULL) ? root : p;node *temp = p;while (temp != root){if (temp->count != 0)return true;elsetemp = temp->fail;}}return false;
}
int main()
{int n;node *root = new node();cin >> n;string keyword;while (n--){cin >> keyword;Insert(root, keyword);}GetFail(root);string str;cin >> str;if (Query(root, str))cout << "YES" << endl;elsecout << "NO" << endl;return 0;
}

上面的代码是理论上正确的代码,但是如果那这个去提交的话会超时,把84行while修改为if以后就可以通过了,但是修改以后逻辑上是错误的代码。

下面给一个AC自动机功能扩展代码:

#include <iostream>
#include <queue>
#include <vector>
#include <string>
#include <string.h>
#include <fstream>
using namespace std;#define size 26struct ACNode
{ACNode *fail;          //失败指针ACNode *next[size];    //Tire每个节点有26个子节点,分别对应26个英文字母int count;             //该节点是否为单词的末尾节点,也可用于判断模式是否重复int patternNo;         //该节点是第几个模式,查找的时候用于还原用于ACNode(){fail = NULL;count = 0;patternNo = -1;memset(next, NULL, sizeof(next));}
};
void Insert(ACNode *root, string str, int patterNo)
{ACNode *p = root;int i = 0, index;for (int i = 0; i < str.length(); i++){index = str[i] - 'a';if (p->next[index] == NULL)p->next[index] = new ACNode();p = p->next[index];}p->count++;p->patternNo = patterNo;
}
void GetFail(ACNode *root)
{int i;root->fail = NULL;queue<ACNode*> q;q.push(root);while (q.empty() == false){ACNode *temp = q.front();q.pop();ACNode *p = NULL;for (i = 0; i<size; i++){if (temp->next[i] != NULL){if (temp == root)temp->next[i]->fail = root;else{p = temp->fail;while (p != NULL){if (p->next[i] != NULL){temp->next[i]->fail = p->next[i];break;}p = p->fail;}if (p == NULL)temp->next[i]->fail = root;}q.push(temp->next[i]);}}}
}
int Query(ACNode *root, string str, vector<string> &keySet)
{int cnt = 0, index;ACNode *p = root;for (int i = 0; i < str.length();i++){index = str[i] - 'a';while (p->next[index] == NULL && p != root)p = p->fail;p = p->next[index];p = (p == NULL) ? root : p;ACNode *temp = p;while (temp != root){if (temp->count>0){int patternNo = temp->patternNo;int patternLength = keySet[patternNo].length();cout << i - patternLength + 1 << "  " << keySet[patternNo] << endl;cnt += temp->count;}temp = temp->fail;}}return cnt;
}
int main()
{ifstream in(".\\input.txt");cin.rdbuf(in.rdbuf());int n;ACNode *root = new ACNode();cin >> n;string keyword;vector<string> keySet;for (int i = 0; i < n;i++){cin >> keyword;keySet.push_back(keyword);Insert(root, keyword,i);}GetFail(root);string str;cin >> str;Query(root, str, keySet);return 0;
}

参考博客:
http://www.cppblog.com/mythit/archive/2009/04/21/80633.html
http://www.cnblogs.com/xudong-bupt/p/3433506.html

算法导论—AC自动机相关推荐

  1. KMP算法、AC自动机算法的原理介绍以及Python实现

    KMP算法 要弄懂AC自动机算法,首先弄清楚KMP算法. 这篇文章讲的很好: http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E ...

  2. AC自动机算法及模板

    AC自动机算法及模板 2016-05-08 18:58 226人阅读 评论(0) 收藏 举报  分类: AC自动机(1)  版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 关于 ...

  3. 提高篇 第二部分 字符串算法 第4章 AC自动机

    https://blog.csdn.net/wangyh1008/article/details/81428056 [模板]AC自动机(加强版) 洛谷3796 AC自动机_A_loud_name-CS ...

  4. 数据结构与算法之美笔记——基础篇(下):图、字符串匹配算法(BF 算法和 RK 算法、BM 算法和 KMP 算法 、Trie 树和 AC 自动机)

    图 如何存储微博.微信等社交网络中的好友关系?图.实际上,涉及图的算法有很多,也非常复杂,比如图的搜索.最短路径.最小生成树.二分图等等.我们今天聚焦在图存储这一方面,后面会分好几节来依次讲解图相关的 ...

  5. ac自动机 匹配最长前缀_AC自动机算法

    AC自动机简介: 首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.一个常见的例子就是给出n个单词,再给出一段包 ...

  6. 【BZOJ】2553: [BeiJing2011]禁忌 AC自动机+期望+矩阵快速幂

    [题意]给定n个禁忌字符串和字符集大小alphabet,保证所有字符在集合内.一个字符串的禁忌伤害定义为分割能匹配到最多的禁忌字符串数量(一个可以匹配多次),求由字符集构成的长度为Len的字符串的期望 ...

  7. hdu 2243(poj2778的加强版!(AC自动机+矩阵))

    问你长度为1~N的串中包含了模式串的串总共有几个(先求出总共小于L的单词数(26^1+26^2+26^3+...26^L)..然后再减去不包括所给字符串的单词) 答案要模2^64,直接用unsinge ...

  8. 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂

    [题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...

  9. Aho-Corasick 多模式匹配算法(AC自动机) 的算法详解及具体实现

    多模式匹配 多模式匹配就是有多个模式串P1,P2,P3-,Pm,求出所有这些模式串在连续文本T1-.n中的所有可能出现的位置. 例如:求出模式集合{"nihao","ha ...

最新文章

  1. 动态鼠标指针_推荐8款电脑鼠标指针,让你电脑不再千篇一律
  2. boost::hana::remove_at_c用法的测试程序
  3. Spring Stateless State Security第3部分:JWT +社会认证
  4. Objective-C模版方法(TemplateMethod)
  5. win10雷电3接口驱动_技嘉推出B550 主板首发雷电3接口:40Gbps速率、Intel主控
  6. 快了!CVPR 2019 所有录用论文题目列表刊出,即将开放下载!
  7. java弱引用在安卓中有效吗_Android 软引用和弱引用详解及实例代码
  8. 【自爆系列】如何从整体上削弱一支队伍的技术水平
  9. SQL 错误: ORA-12910
  10. SQL语言 --- 数据定义
  11. PC通过adb连接手机 无需root连接 需要root连接
  12. java模板引擎哪个好_模板引擎比较
  13. 容斥原理(转载http://www.cppblog.com/vici/archive/2011/09/05/155103.html)
  14. 如何撰写和发表SCI论文
  15. AI,让大海永远蔚蓝如诗
  16. 坚果云企业版服务器端,坚果云团队版和企业版的区别
  17. 建木(Jianmu)----迈出建木第一步创建项目分组
  18. Zcash使用工具nheqminer用cpu挖矿
  19. KiCAD元件库快速制作
  20. 全球23家电信巨头布局区块链、数字货币 打响“支付翻身战”

热门文章

  1. 微软亚洲研究院成立理论中心,以理论研究打破AI发展瓶颈
  2. UI架构设计五 — DTA文件使用脚本自动生成
  3. 铰接板荷载横向分布影响线竖标表 计算程序2017
  4. 整理 酷炫 Android 开源UI框架 Navigation
  5. Python+vtk 实现激光点云数据可视化学习(2021.7.12)
  6. 基于物联网技术的智能家居设计
  7. MATLAB绘制实指数信号
  8. MFC中的Resource.h文件理解
  9. blob开头的文件下载_Blob下载文件流
  10. 有序聚类的matlab实现