Aho_Corasick自动机(AC自动机)
首先,AC自动机不是Accept自动机,别以为把这段代码复制到OJ上就全都自动AC了……
在字符串失配的时候确定转移的节点。AC难点就是指针的算法,看下面这么多图:










#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#define REP(i, s, n) for(int i = s; i <= n; i ++)
#define RAP(i, n, s) for(int i = n; i >= s; i --)
#define now ch[x][c]
using namespace std;
const int maxn = + ;
const int maxsig = ;
char S[ + ];
int n;
inline void read(int &x){
x = ; int sig = ; char ch = getchar();
while(!isdigit(ch)) { if(ch == '-') sig = -; ch = getchar(); }
while(isdigit(ch)) x = * x + ch - '', ch = getchar();
x *= sig; return ;
}
inline void write(int x){
if(x == ) { putchar(''); return; }
if(x < ) putchar('-'), x = -x;
int len = , buf[];
while(x) buf[len ++] = x % , x /= ;
RAP(i, len - , ) putchar(buf[i] + ''); return ;
}
namespace Aho_Corasick{
int ch[maxn][maxsig], val[maxn], f[maxn], last[maxn], len[maxn], ms;
void AC_init(){
ms = ;
memset(ch, , sizeof(ch));
memset(val, , sizeof(val));
memset(f, , sizeof(f));
memset(last, , sizeof(last));
memset(len, , sizeof(len));
return ;
}
void insert(char* s, int v){
int x = , i;
for(i = ; s[i] != '\0'; i ++){
int c = s[i] - ''; if(!now) now = ++ ms; x = now;
}
val[x] = v; len[x] = i; return ;
}
void getfail(){
queue<int> Q;
REP(i, , maxsig - ) if(ch[][i]) Q.push(ch[][i]);
while(!Q.empty()){
int x = Q.front(); Q.pop();
REP(c, , maxsig - ){
if(!now) { now = ch[f[x]][c]; continue; }
Q.push(now); int cur = f[x];
while(cur && !now) cur = f[cur];
f[now] = ch[cur][c]; last[now] = val[f[now]] ? f[now] : last[f[now]];
}
}
return ;
}
void AC_print(int i, int j){
if(j){
write(val[j]); printf(": ");
write(i - len[j] + ); printf(" to ");
write(i); putchar('\n');
AC_print(i, last[j]);
}
return ;
}
void solve(char* T){
int cur = ;
for(int i = ; T[i] != '\0'; i ++){
cur = ch[cur][T[i] - ''];
if(val[cur]) AC_print(i, cur);
else if(last[cur]) AC_print(i, last[cur]);
}
return ;
}
}using namespace Aho_Corasick;
bool init(){
read(n); if(!n) return false;
AC_init();
REP(i, , n) scanf("%s", S), insert(S, i);
return true;
}
void work(int cur){
getfail();
scanf("%s", S);
printf("Case "); write(cur);
printf(":\n");
solve(S);
return ;
}
void print(){ return ;
}
int main(){
int Case = ;
while(init()) work(Case ++);
return ;
}
Aho_Corasick自动机(AC自动机)的更多相关文章
- 后缀自动机/回文自动机/AC自动机/序列自动机----各种自动机(自冻鸡) 题目泛做
题目1 BZOJ 3676 APIO2014 回文串 算法讨论: cnt表示回文自动机上每个结点回文串出现的次数.这是回文自动机的定义考查题. #include <cstdlib> #in ...
- 从Trie谈到AC自动机
ZJOI的SAM让我深受打击,WJZ大神怒D陈老师之T3是SAM裸题orz...我还怎么混?暂且写篇`从Trie谈到AC自动机`骗骗经验. Trie Trie是一种好玩的数据结构.它的每个结点存的是字 ...
- 多模字符串匹配算法之AC自动机—原理与实现
简介: 本文是博主自身对AC自动机的原理的一些理解和看法,主要以举例的方式讲解,同时又配以相应的图片.代码实现部分也予以明确的注释,希望给大家不一样的感受.AC自动机主要用于多模式字符串的匹配,本质上 ...
- AC自动机详解(附加可持久化AC自动机)
AC自动机 AC自动机,说白了就是在trie树上跑kmp(其实个人感觉比kmp容易理解).是一种多匹配串,单个主串的匹配.概括来说,就是将多个匹配串构造一个trie树,对于每个trie树的节点构造nx ...
- 浅谈算法——AC自动机
在学习AC自动机之前,你需要两个前置知识:Trie树,KMP 首先我们需要明白,AC自动机是干什么的(用来自动AC的) 大家都知道KMP算法是求单字符串对单字符串的匹配问题的,那么多字符在单字符上匹配 ...
- [Alg] 文本匹配-多模匹配-AC自动机
1. 简介 AC自动机是一种多模匹配的文本匹配算法. 如果采用naive的方法,即依次比较文本串s中是否包含模式串p1, p2,...非常耗时.考虑到这些模式串中可能具有相同子串,可以利用已经比较过的 ...
- 字典树基础进阶全掌握(Trie树、01字典树、后缀自动机、AC自动机)
字典树 概述 字典树,又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它 ...
- hdu 2896 AC自动机
// hdu 2896 AC自动机 // // 题目大意: // // 给你n个短串,然后给你q串长字符串,要求每个长字符串中 // 是否出现短串,出现的短串各是什么 // // 解题思路: // / ...
- hdu 3065 AC自动机
// hdu 3065 AC自动机 // // 题目大意: // // 给你n个短串,然后给你一个长串,问:各个短串在长串中,出现了多少次 // // 解题思路: // // AC自动机,插入,构建, ...
随机推荐
- git的一些概念和技巧
1. 分支代表最后三个commit(即HEAD, HEAD^和HEAD~2),前一个commit,也用HEAD~1 2. 查看一个文件的改动历史git log (--pretty=oneline) - ...
- Mysql update error: Error Code: 1175. You are using safe update mode and you tried to update a table
Mysql update error: Error Code: 1175. You are using safe update mode and you tried to update a table ...
- Android更新UI的几种方式
之前做过一个Android采集心电图数据的程序,那才是真正的多线程,之前写的小程序:比如下载个文件,从socket接受大一点的数据流然后在ui上更新进度,我都感觉这就叫做多线程了,其实这啥都不算,用个 ...
- Android真正意义上的无限轮播Banner
在android开发的时候,经常会使用到轮播图,对于这种效果,一般情况下,我们都会使用一种叫做ViewPager的来实现. 传统的实现逻辑是自定义一个View继承ViewPager,在适配器中 将co ...
- 进程外session(session保存在sqlserver)
.Session保存在SQLServer中配置方法 )运行.NetFramework安装目录下对应版本的aspnet_regsql.exe 来创建相关的数据库.表和存储过程等,比如: C:\Windo ...
- visual studio中的一些实用的快捷键
重置开发环境:使得开发工具恢复默认状态 方法:工具->导入和导出设置导向->重置所有设置->不保存 显示行号: 方法:工具->选项->所有语言->行号 在编程过程中 ...
- left ,right ,cross ,full/left outer join/区别 详解
--创建测试表wwif OBJECT_ID('qq') is not null drop table qqcreate table qq([序号] varchar(5),[内容1] varchar(1 ...
- MemCache缓存和C#自带的Cache缓存
1.MemCache: //初始化 static SockIOPool _pool; // 创建Memcached private static MemcachedClient Create(stri ...
- NSString截取字符串
NSString 是经常会用到的,很多时候需要对字符串进行一些处理,本文简单介绍字符串截取操作: 比如: 1.定义一个字符串a, 截取a的某一个部分(子串) NSString *a = @" ...
- jquery find选择器在不同浏览器下的差异
初步测试,5000个节点的隐藏. 代码如下: <!doctype html> <html lang="en"> <head> <scrip ...