首页 > 代码库 > AC自动机 HDU2222
AC自动机 HDU2222
学了KMP算法,就能解决大部分的单模匹配,但是当有多个搜索词的时候就捉襟见肘了。然后就又有一个新知识(对我来说),AC自动机。
之前也听说过,但是看到这个东西排在lrj的书的后面,我就被吓到了,所以还是说不能害怕做题,要敢于正视问题,才能解决问题。
和KMP类似,AC自动机放在字典树的基础上,增加了类似KMP的next数组的东西,里面叫做失败指针,当然好像kmp那个next也叫失败数组。。。
原理详解: 点击
不过我觉的还是要结合题来看比较好理解,还没有用数组的映射实现过,只是用了指针(还写了两遍Orz,学完后还有昨天),有空把数组的学会补上 Mark
题意:给定字典,多个单词
再给一个句子,问字典中有多少个单词再句子中出现过。改造可以在字典树的里面增加元素(字符串,字符串长度,标记等等)
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> using namespace std; const int MAXN = 1e6 + 5; struct Trip { Trip* next[26]; Trip* fail; int sum; Trip() { memset(next, 0, sizeof(next)); fail = NULL; sum = 0; } }; string str; Trip *root; Trip *q[MAXN]; int cnt = 0; int n,t; void init() { root = new Trip(); } void Insert(string s) { Trip *p = root; int n = s.size(); for(int k = 0; k < n; k++) { int i = s[k] - ‘a‘; if(p->next[i] == NULL) { p->next[i] = new Trip(); } p = p->next[i]; } p->sum ++ ; } void build_fail_pointer() { int head = 0; int tail = 1; memset(q, 0, sizeof(q)); q[head] = root; while(head < tail) { Trip *p = q[head++]; for(int i = 0; i < 26; i++) { if(p->next[i] != NULL) { q[tail++] = p->next[i]; if(p == root) { p->next[i]->fail = root; } else { Trip *q = p->fail; if(q->next[i] != NULL) { p->next[i]->fail = q->next[i]; } else { while(q) { if(q->next[i] != NULL) { p->next[i]->fail = q->next[i]; break; } q = q->fail; } if(q == NULL) p->next[i]->fail = root; } } } } } } void ac_solve(string s) { Trip *p = root; int n = s.size(); for(int i = 0; i < n; i++) { int k = s[i] - ‘a‘; while(p->next[k] == NULL && p != root) p = p->fail; p = p->next[k]; if(p == NULL) p = root; Trip* temp = p; while(temp != root) { if(temp->sum >= 0) { cnt += temp->sum; temp->sum = -1; } else break; temp = temp->fail; } } } int main() { std::ios_base::sync_with_stdio(false); cin>>t; while(t--) { cnt = 0; init(); cin>>n; while(n--) { cin>>str; Insert(str); } build_fail_pointer(); cin>>str; ac_solve(str); printf("%d\n", cnt); delete root; } return 0; }
AC自动机 HDU2222
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。