AC自动机以及KMP模板
2017-07-31 19:39
351 查看
AC自动机
Aho-Corasick automaton,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法。
要学会AC自动机,我们必须知道什么是Trie,也就是字典树。Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。
应用
一个常见的例子就是给出n个单词,再给出一段包含m个字符的文章,让你找出有多少个单词在文章里出现过。
要搞懂AC自动机,先得有模式树(字典树)Trie和KMP模式匹配算法的基础知识。AC自动机算法分为3步:构造一棵Trie树,构造失败指针和模式匹配过程。
//AC自动机模板 #include <bits/stdc++.h> using namespace std; const int maxn = 1e7 + 5; const int MAX = 10000000; struct node { node *next[26]; node *fail; int sum; }; node *root; node *q[MAX]; //队列 char partner[maxn]; char s[105]; int head, tail; int cnt; //建立字典树 void Insert(char *s) { node *p = root; for(int i=0; s[i]; i++) { int x = s[i] - 'a'; if(p->next[x]==NULL) { node *temp = (node *)malloc(sizeof(node)); for(int j=0; j<26; j++) temp->next[j] = 0; temp->sum = 0; temp->fail = 0; p->next[x] = temp; } p = p->next[x]; } p->sum++; } //用队列实现fail void build_fail_pointer() { head = 0; tail = 1; q[head] = root; while(head < tail) { node *temp = q[head++]; for(int i=0; i<26; i++) { if(temp->next[i]) { if(temp == root) { temp->next[i]->fail = root; } else { node *r = temp->fail; while(r) { if(r->next[i]) { temp->next[i]->fail = r->next[i]; break; } r = r->fail; } if(r==NULL) temp->next[i]->fail = root; } q[tail++] = temp->next[i]; } } } } //匹配单词 void ac_automation(char *partner) { node *p = root; int len = strlen(partner); for(int i=0; i<len; i++) { int x = partner[i]-'a'; while(!p->next[x] && p!=root) p = p->fail; p = p->next[x]; if(!p) p = root; node *temp = p; while(temp != root) { if(temp->sum >= 0) { cnt += temp->sum; temp->sum = -1; } else break; temp = temp->fail; } } } int main() { int T; scanf("%d", &T); while(T--) { root = (node *)malloc(sizeof(node)); for(int i=0; i<26; i++) root->next[i] = 0; root->sum = 0; root->fail = 0; int n; scanf("%d", &n); getchar(); for(int i=1; i<=n; i++) { gets(s); Insert(s); } gets(partner); cnt = 0; build_fail_pointer(); ac_automation(partner); printf("%d\n", cnt); } return 0; }
//KMP模板
//T是模式串
void getNext(char *T)
{
int j, k, tlen = strlen(T);
j = 0; k = -1; next[0] = -1;
while(j < tlen)
if(k == -1 || T[j] == T[k])
next[++j] = ++k;
else
k = next[k];
}
//返回模式串T在主串S中首次出现的位置
//返回的位置是从0开始的。
int KMP_Index(char *T, char *S)
{
int i = 0, j = 0;
getNext(T);
int slen = strlen(S);
int tlen = strlen(T);
while(i < slen && j < tlen)
{
if(j == -1 || S[i] == T[j])
{
i++; j++;
}
else
j = next[j];
}
if(j == tlen)
return i - tlen;
else
return -1;
}
AC自动机模板题目:HDU 2222
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222
相关文章推荐
- 模板_KMP和AC自动机
- 【模板】kmp以及扩展kmp
- KMP && AC自动机模板
- KMP两种写法以及AC自动机失配数组间的区别
- hdoj 1686 Oulipo 【kmp(模板)】
- KMP 模板
- kmp模板----------------hdu1686
- Vue--基础模板语法以及计算属性
- JavaEE开发之SpringBoot整合MyBatis以及Thymeleaf模板引擎
- AC自动机 模板 hdu 2222
- 泛型编程、STL的概念、STL模板思想及其六大组件的关系,以及泛型编程(GP)、STL、面向对象编程(OOP)、C++之间的关系
- HDOJ-2222 (AC自动机模板)
- 【洛谷】3796 【模板】AC自动机(加强版)
- hdu 2222 ac自动机更新模板 for onSite contest
- 项目开发计划模板-根据经验以及参考资料整理
- 用C++类模板实现栈结构出现的问题以及思考
- POJ 3461 Oulipo [KMP模板题]
- poj 2406 poj 1961 个人对吉大KMP模板的理解 KMP 基础题--找周期串
- Oulipo----poj3461(kmp模板)
- 白书上的AC自动机模板