AC自动机模板
来源:互联网 发布:淘宝商家注册要多少钱 编辑:程序博客网 时间:2024/06/04 01:18
AC自动机讲解:http://blog.csdn.net/creatorx/article/details/71100840 ------------>(讲的很简单也很清楚的博文地址)
AC自动机理解的部分还是很好理解的,字典树加上KMP的匹配失败转移的思想。
只是AC自动机的代码部分比较难理解。
以下是自己对AC自动机模板以及理解部分。
模板:
#include <iostream>#include <cstdio>#include <cstring>#include <cstring>#include <algorithm>#include <queue>using namespace std;const int maxn=1e6+50;struct Tries{ int nxt[maxn][26],fail[maxn],end[maxn]; /* nxt[i][j] 数组储存第i个节点的'a'+j字符储存的节点; fail[i]表示第i个fail储存的匹配失败应该转移的节点; end[i]表示从根节点到第i个节点的这个字符串出现的次数; */ int root,L; /* L 为节点的编号; root 为根节点; */ int newnode(){ for(int i = 0; i < 26 ; i++ ) nxt[L][i]=-1; end[L++]=0; return L-1; } /* 创立新节点; */ void init(){ L=0; root = newnode(); } /* 初始化; */ void insert(char buf[]){ int len = strlen(buf); int now = root; for(int i = 0; i < len ; i++ ) { if(nxt[now][buf[i]-'a'] == -1) nxt[now][buf[i]-'a'] =newnode(); now = nxt[now][buf[i]-'a']; } end[now]++ ; } /* 插入新的字符串; 如果该字符没有在该位置出现过,则建立新的节点; 如果出现过,则继续向后更新; 每次对该字符串的数目进行更新; */ void build(){ queue<int>Q; fail[root] = root; for(int i = 0; i < 26; i++ ) if(nxt[root][i]==-1) nxt[root][i] = root; else { fail[nxt[root][i]] = root;/* *** */ Q.push(nxt[root][i]); } while(!Q.empty()) { int now = Q.front(); Q.pop(); for(int i = 0;i < 26; i++ ) if(nxt[now][i]==-1)//如果该节点的子节点都不存在,那么该子节点节点变为该节点的转移节点的子节点 nxt[now][i] = nxt[fail[now]][i]; /* *** */ else//如果存在,那么该子节点的转移节点为该节点的转移节点的子节点,该子节点入队列 { fail[nxt[now][i]] = nxt[fail[now]][i]; Q.push(nxt[now][i]); } } } /* 创建匹配失败时的转移数组; 根节点与第一层部分匹配失败后转移至根节点部分; 其他部分则转移至该字符出现过的节点位置; */ int query(char buf[]) { int len = strlen(buf); int now = root; int res = 0; for(int i = 0;i < len ; i++ )//如果子节点存在,则顺着该链一直匹配下去;如果不存在就一直转移,直到存在或者转移到根节点(now会更新到根节点) { now = nxt[now][buf[i]-'a']; int tmp = now; while( tmp != root) { res += end[tmp]; end[tmp] = 0; tmp = fail[tmp]; } } return res; } /* 输入需要拿来匹配的串; 一次次的对当前串的各位进行匹配,如果包含当前字符的串在字典树中有出现,则答案累计加上该出现次数,且跳转转移节点进行计数; 因为end记录的是出现的次数,所以在需要匹配的串中如果有该字符,那么进行清0,则能保证字典树中的串在母串中出现一次; */};Tries AC;
hdu2222:
#include <iostream>#include <algorithm>#include <cstdio>#include <cstdlib>#include <cstring>#include <queue>using namespace std;const int maxn=1e6+50;struct Tries{ int nxt[maxn][26],fail[maxn],end[maxn]; /* nxt[i][j] 数组储存第i个节点的'a'+j字符储存的节点; fail[i]表示第i个fail储存的匹配失败应该转移的节点; end[i]表示从根节点到第i个节点的这个字符串出现的次数; */ int root,L; /* L 为节点的编号; root 为根节点; */ int newnode(){ for(int i = 0; i < 26 ; i++ ) nxt[L][i]=-1; end[L++]=0; return L-1; } /* 创立新节点; */ void init(){ L=0; root = newnode(); } /* 初始化; */ void insert(char buf[]){ int len = strlen(buf); int now = root; for(int i = 0; i < len ; i++ ) { if(nxt[now][buf[i]-'a'] == -1) nxt[now][buf[i]-'a'] =newnode(); now = nxt[now][buf[i]-'a']; } end[now]++ ; } /* 插入新的字符串; 如果该字符没有在该位置出现过,则建立新的节点; 如果出现过,则继续向后更新; 每次对该字符串的数目进行更新; */ void build(){ queue<int>Q; fail[root] = root; for(int i = 0; i < 26; i++ ) if(nxt[root][i]==-1) nxt[root][i] = root; else { fail[nxt[root][i]] = root;/* *** */ Q.push(nxt[root][i]); } while(!Q.empty()) { int now = Q.front(); Q.pop(); for(int i = 0;i < 26; i++ ) if(nxt[now][i]==-1) nxt[now][i] = nxt[fail[now]][i]; /* *** */ else { fail[nxt[now][i]] = nxt[fail[now]][i]; Q.push(nxt[now][i]); } } } /* 创建匹配失败时的转移数组; 根节点与第一层部分匹配失败后转移至根节点部分; 其他部分则转移至该字符出现过的节点位置; */ int query(char buf[]) { int len = strlen(buf); int now = root; int res = 0; for(int i = 0;i < len ; i++ ) { now = nxt[now][buf[i]-'a']; int tmp = now; while( tmp != root) { res += end[tmp]; end[tmp] = 0; tmp = fail[tmp]; } } return res; } /* 输入需要拿来匹配的串; 一次次的对当前串的各位进行匹配,如果包含当前字符的串在字典树中有出现,则答案累计加上该出现次数,且跳转转移节点进行计数; 因为end记录的是出现的次数,所以在需要匹配的串中如果有该字符,那么进行清0,则能保证字典树中的串在母串中出现一次; */};Tries AC;char str[maxn];int main(){ int t; int n; scanf("%d",&t); while(t--) { AC.init(); scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%s",str); AC.insert(str); } AC.build(); scanf("%s",str); printf("%d\n",AC.query(str)); } return 0;}
阅读全文
1 0
- 【AC自动机】AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板 hdu2222
- AC自动机模板
- AC自动机模板
- 数据结构--AC自动机--模板
- ac自动机模板
- AC自动机模板
- AC自动机模板
- hdu2222 ac自动机模板
- ac自动机模板。。。。。
- AC自动机模板 LA4670
- AC自动机模板
- stdlib.h包含的函数
- 8.11
- 2017/8/11
- license
- 冒泡排序
- AC自动机模板
- QAQ & 君临天下 || 天行九歌
- 关于冒泡排序的若干回顾经验
- java笔试题总结
- REST类型接口测试脚本开发
- Android 常用sql语句之联表查询
- 8.11
- ACboy needs your help again!
- 8.11