AC自动机入门+模板 (HDU 2222)
2016-05-10 23:17
375 查看
Aho-Corasick算法是多模式匹配中的经典算法
多模式匹配就是有多个模式串P1,P2,P3…,Pm,求出所有这些模式串在连续文本T1….n中的所有可能出现的位置。
步骤
1.建立模式的Trie
2.给Trie添加失败路径
3.根据AC自动机,搜索待处理的文本
重难点
构造失败指针
设这个节点上的字母为C, 沿着他父亲的失败指针走,直到走到 节点,他的儿子中也有字母为C的节点。然后把当前节点的失败指针指向那个字母也为C的节点。如果一直走到了root都没找到,那就把失败指针指向root。
使用广度优先搜索BFS,层次遍历节点来处理,每一个节点的失败路径。
特殊处理:第二层要特殊处理,将这层中的节点的失败路径直接指向父节点(也就是根节点)。
例如(图片引用自网络)
模板 (HDU2222)
给几个关键字和一个模板串,求关键字在模板串中出现了几次
多模式匹配就是有多个模式串P1,P2,P3…,Pm,求出所有这些模式串在连续文本T1….n中的所有可能出现的位置。
步骤
1.建立模式的Trie
2.给Trie添加失败路径
3.根据AC自动机,搜索待处理的文本
重难点
构造失败指针
设这个节点上的字母为C, 沿着他父亲的失败指针走,直到走到 节点,他的儿子中也有字母为C的节点。然后把当前节点的失败指针指向那个字母也为C的节点。如果一直走到了root都没找到,那就把失败指针指向root。
使用广度优先搜索BFS,层次遍历节点来处理,每一个节点的失败路径。
特殊处理:第二层要特殊处理,将这层中的节点的失败路径直接指向父节点(也就是根节点)。
例如(图片引用自网络)
模板 (HDU2222)
给几个关键字和一个模板串,求关键字在模板串中出现了几次
#include <bits/stdc++.h> using namespace std; struct Trie { int next[500010][26],fail[500010],end[500010]; int root,L; int newnode() { for(int i = 0;i < 26;i++) next[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 a3b2 = root; for(int i = 0;i < len;i++) { if(next[now][buf[i]-'a'] == -1) next[now][buf[i]-'a'] = newnode(); now = next[now][buf[i]-'a']; } end[now]++; } void build() { queue<int>Q; fail[root] = root; for(int i = 0;i < 26;i++) if(next[root][i] == -1) next[root][i] = root; else { fail[next[root][i]] = root; Q.push(next[root][i]); } while( !Q.empty() ) { int now = Q.front(); Q.pop(); for(int i = 0;i < 26;i++) if(next[now][i] == -1) next[now][i] = next[fail[now]][i]; else { fail[next[now][i]]=next[fail[now]][i]; Q.push(next[now][i]); } } } int query(char buf[]) { int len = strlen(buf); int now = root; int res = 0; for(int i = 0;i < len;i++) { now = next[now][buf[i]-'a']; int temp = now; while( temp != root ) { res += end[temp]; end[temp] = 0; temp = fail[temp]; } } return res; } void debug() { for(int i = 0;i < L;i++) { printf("id = %3d,fail = %3d,end = %3d,chi [",i,fail[i],end[i]); for(int j = 0;j < 26;j++) printf("%2d",next[i][j]); printf("]\n"); } } }; char buf[1000010]; Trie ac; int main() { int T; int n; scanf("%d",&T); while( T-- ) { scanf("%d",&n); ac.init(); for(int i = 0;i < n;i++) { scanf("%s",buf); ac.insert(buf); } ac.build(); scanf("%s",buf); printf("%d\n",ac.query(buf)); } return 0; }
相关文章推荐
- 文章标题 使用ajaxFileupload+struts2完成文件的上传以及回显到jsp的链接地址
- Android录音--AudioRecord、MediaRecorder
- 将配置文件中分属性封装成对象
- Servlet/JSP-01 Servlet及其生命周期
- mys数据操
- 复杂对象写入文件
- [SCU 4503] TooEasy Or TooDifficult (Manacher+xor-Trie)
- 谷歌浏览器控制台使用
- 从数据库中往solr中导入数据之1
- struts2中的jsp值传到后台action接收的三种方法
- Drawerlayout
- android权限大全
- hdu 4101 Ali and Baba【BFS好题】
- c++第五次作业
- java的栈与堆(基本数据类型与包装数据类型)详解
- uvalive3608(二分 + DP)
- c++作业5
- 20159315《网络攻击与防范》第十周学习总结
- 第四篇——Spring音乐登录界面设计及实现(C#)
- 02. python使用mysqldb连接数据库操作方法示例详解