AC automation 模板
/*
1.对n个字符串构造tire树 insertWord(node *root, char *word);
2.bfs构造fail指针 makeFail(node *root);
3.基于以上两点的查询 query(node *root, char *str);
*/
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
const int N1 = + ;
const int N2 = + ;
char key[N1];
char desc[N2];
struct node
{
node *next[];
int cnt;
node *fail;
node(){for(int i=; i<; ++i) next[i] = NULL; fail = NULL; cnt = ;}
};
void insertWord(node *root)//构造trie树
{
node *cur = root;
int n = strlen(key);
for(int i=; i<n; ++i)
{
int index = key[i] - 'a';
if(cur->next[index] != NULL)
cur = cur->next[index];
else
{
cur->next[index] = new node();
cur = cur->next[index];
}
}
cur->cnt++;
}
void makeFail(node *root)//构造fail指针
{
queue<node*> q;
q.push(root);
node *cur;
while(!q.empty())
{
cur = q.front();
q.pop();
for(int i=; i<; ++i)
{
if(cur->next[i] != NULL)
{
if(cur == root)//与root相连的结点,即第二层的结点的fail指针都是root
cur->next[i]->fail = root;
else
{
node *tmp = cur;
while(tmp->fail != NULL)// why while?
{
if(tmp->fail->next[i] != NULL)
{
cur->next[i]->fail = tmp->fail->next[i];
break;
}
tmp = tmp->fail;
}
if(tmp->fail == NULL)
cur->next[i]->fail = root;
}
q.push(cur->next[i]);
}
}
}
}
int query(node *root)//查询
{
node *cur = root;
node *tmp = NULL;
int i=,cnt=;
while(desc[i])
{
int index = desc[i] - 'a';
while(cur!=root && cur->next[index] == NULL)
cur = cur->fail;
if(cur->next[index] != NULL)
{
cur = cur->next[index];
tmp = cur;
while(tmp != root && tmp->cnt!=)
{
cnt += tmp->cnt;
tmp->cnt = ;
tmp = tmp->fail;
}
}
i++;
}
return cnt;
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
node *root = new node();
scanf("%d",&n);
for(int i=; i<n; ++i)
{
scanf("%s",key);
insertWord(root);
}
makeFail(root);
scanf("%s",desc);
int ans = query(root);
printf("%d\n",ans);
}
return ;
}
//多串匹配,n个模式字符串构成AC自动机,然后目标串去匹配,看目标串中有多少个模式串
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
/*
根结点的fail指针为NULL,根结点的直接子结点的fail指针为root,很明显,当一个字符都不匹配时,从根结点再开始匹配
每个结点的fail指针都是由它父结点的fail指针决定的。
*/
const int N = + ;
struct node
{
node *next[],*fail;
int cnt;
node(){for(int i=; i<; ++i) next[i] = NULL; fail = NULL; cnt = ;}
};
void insertWord(node *root, char *word)
{
node *cur = root;
int i = ;
while(word[i])
{
int index = word[i] - 'a';
if(cur->next[index] == NULL)
cur->next[index] = new node();
cur = cur->next[index];
++i;
}
cur->cnt ++;
}
char str[N];
void makeFail(node *root)
{
node *cur,*tmp;
queue<node*> q;
q.push(root);
while(!q.empty())
{
cur = q.front();
q.pop();
for(int i=; i<; ++i)
{
if(cur->next[i] != NULL)
{
q.push(cur->next[i]);
if(cur == root)//如果当前结点是root,那么它的直接孩子结点的fail指针指向root
cur->next[i]->fail = root;
else
{
tmp = cur;
while(tmp->fail != NULL)//because root->fail == NULL,如果到了这个地步,说明当前字符串没有后缀
{
if(tmp->fail->next[i] != NULL)
{
cur->next[i]->fail = tmp->fail->next[i];
break;
}
tmp = tmp->fail;
}
if(tmp->fail == NULL)
cur->next[i]->fail = root;
}
}
}
}
} // how to query???
int query(node *root, char *str)
{
node *cur = root;
node *tmp = NULL;
int i = , cnt = ;
while(str[i])
{
int index = str[i] - 'a';
while(cur!=root && cur->next[index]==NULL)//如果失配,那么直接跳到fail指针处去匹配
cur = cur->fail;
if(cur->next[index] != NULL)
{
cur = cur->next[index];//如果当前字符匹配成功,则跳到那个字符,
tmp = cur;
//这就是为什么Ac自动机效率高的缘故,根据fail指针,跳到当前字符串的最长后缀去
//如果tmp->cnt != 0 说明存在该最长后缀形成的字符串
while(tmp->cnt!=)
{
cnt += tmp->cnt;
tmp->cnt = ;
tmp = tmp->fail;
}
}
++i;
}
return cnt;
}
int main()
{
int t,n;
scanf("%d",&t);
char word[];
while(t--)
{
node *root = new node();
scanf("%d",&n);
for(int i=; i<n; ++i)
{
scanf("%s",word);
insertWord(root, word);
}
scanf("%s",str);
makeFail(root);
int ans = query(root, str);
printf("%d\n",ans);
}
return ;
给定n个模式串,长度均不超过m,和一个目标串(长度为L),问目标串中包含多少个模式串(可重叠
的)。
暴力算法是一个个模式串去与目标串匹配,时间复杂度是O(n*m*L)
有更好的算法是AC自动机,时间复杂度是O(n)(这个怎么算来着??)
AC自动机分为两步,1.构建trie树。2.构建fail指针。正是这个fail指针将时间复杂度给大大缩小了
fail指针是匹配失败时,该跳到那个结点去重新匹配
fail指针是指向当前字符串的最长后缀,比如she的fail指针应该指向he或e或root(即指向存在的最长后
缀)
所以当前结点的fail指针由父结点的fail指针所决定
学习资料:http://www.cppblog.com/menjitianya/archive/2014/07/10/207604.html
AC automation 模板的更多相关文章
- HDU 2222 AC自动机模板题
题目: http://acm.hdu.edu.cn/showproblem.php?pid=2222 AC自动机模板题 我现在对AC自动机的理解还一般,就贴一下我参考学习的两篇博客的链接: http: ...
- Match:Keywords Search(AC自动机模板)(HDU 2222)
多模匹配 题目大意:给定很多个字串A,B,C,D,E....,然后再给你目标串str字串,看目标串中出现多少个给定的字串. 经典AC自动机模板题,不多说. #include <iostream& ...
- HDU 3065 (AC自动机模板题)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3065 题目大意:多个模式串,范围是大写字母.匹配串的字符范围是(0~127).问匹配串中含有哪几种模 ...
- HDU 2896 (AC自动机模板题)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2896 题目大意:多个模式串.多个匹配串.其中串的字符范围是(0~127).问匹配串中含有哪几个模式串 ...
- HDU 2222(AC自动机模板题)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2222 题目大意:多个模式串.问匹配串中含有多少个模式串.注意模式串有重复,所以要累计重复结果. 解题 ...
- HDU 2222 (AC自动机模板题)
题意: 给一个文本串和多个模式串,求文本串中一共出现多少次模式串 分析: ac自动机模板,关键是失配函数 #include <map> #include <set> #incl ...
- hdu 2222 Keywords Search ac自动机模板
题目链接 先整理一发ac自动机模板.. #include <iostream> #include <vector> #include <cstdio> #inclu ...
- KMP与AC自动机模板
HDU 1711 Number Sequence(KMP模板题) http://acm.hdu.edu.cn/showproblem.php?pid=1711 #include<bits/std ...
- HDU3695(AC自动机模板题)
题意:给你n个字符串,再给你一个大的字符串A,问你着n个字符串在正的A和反的A里出现多少个? 其实就是AC自动机模板题啊( ╯□╰ ) 正着query一次再反着query一次就好了 /* gyt Li ...
随机推荐
- Delphi的TService的輸入桌面切換(服务程序)(windows登录界面如何截图)(使用了OpenDesktop和GetThreadDesktop等API)
dfm: object CopyDeskService: TCopyDeskService OldCreateOrder = False OnCreate = ServiceCreate OnD ...
- 【Demo 0008】标签控制器
本章学习要点: 1. 了解标签控制器基础知识; 2. 掌握标签控制器层次结构; 3. 掌握标签控制器基本用法; 4. 掌握自定义标签控制器: ...
- json介绍及简单示例
JSON的定义: 一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性.业内主流技术为其提供了完整的解决方案(有点类似于正则表达式 ,获得了当今大部分语言的支持),从而可以在不同平台间进行数据 ...
- IE6_一些简单bug
1.IE6调整窗口大小的 Bug 当把body居中放置,改变IE浏览器大小的时候,任何在body里面的相对定位元素都会固定不动了.给body定义position:relative;就行了. 2.避免百 ...
- 14.5.4 InnoDB File-Per-Table Tablespaces 每个表一个文件
14.5.4 InnoDB File-Per-Table Tablespaces 每个表一个文件 从历史上看, 所有的InnoDB 表和索引是存储在system 表空间, 这个整体的方法是针对机器专注 ...
- docker 创建本地镜像服务器
1.docker pull registry //下载registry 镜像,registry 为docker 官方提供的一个镜像, 我们可以用它来创建本地的docker私有仓库. docker:/r ...
- 不起眼的 z-index 却能牵扯出这么大的学问(转)
z-index在日常开发中算是一个比较常用的样式,一般理解就是设置标签在z轴先后顺序,z-index值大的显示在最前面,小的则会被遮挡,是的,z-index的实际作用就是这样. 但是你真的了解z-in ...
- Cocos2d-x 3.1.1 Lua实例-AccelerometerTest(重力加速计)
Cocos2d-x 3.1.1 Lua实例-AccelerometerTest(重力加速计) 本篇博客介绍Cocos2d-x的第一个实例--重力加速计測试.效果图(注:这里无法模拟重力感应): --[ ...
- 新出台的治理iMessage垃圾短信的规则
工信部拟制定<通信短信息服务管理规定>,为治理垃圾短信提供执法根据.当中,对于苹果iMessage垃圾信息泛滥现象,工信部也将跟踪研究技术监測和防范手段.这意味着长期以来处于监管" ...
- linux根据部署jenkins
1. Jenkins 下载 Jenkins 下载网址:http://jenkins-ci.org/ 2. Jenkins 安装 (1) 安装JDK JDK下载:http://www.oracle.co ...