HDU 3065 病毒侵袭持续中(AC自动机模板)
2015-04-30 15:14
399 查看
题目大意:输出每个模板串出现的次数。
AC自动机模板题。
AC自动机个人体会:
再了解AC自动机之前,建议先看看KMP和Trie树。
首先看Node结构体内的各个成员所代表的含义:
ch:children缩写,这个结点后的所有儿子。如果串1:abcde的d的编号为4,另外串2:abcdf的d也会编号为4(其实abcd四个都是编号一样的),那么d的儿子有e和f;
fail:该结点失配后,应该跳去下一个匹配的结点的编号。比如abcdf的f失配后,很大可能性跳去e(得看有多少个串了);
last:表示沿着该结点的fail走,遇到的第一个单词结尾的结点。
这里约定好当某结点的失配指针为root时,则下一个字符将会和根节点的儿子们比较(根节点为虚拟结点);当ch[i]为-1时,表示这个儿子不存在。
Insert函数和Trie树中的插入是一样的。
然而重头戏是Build函数,构造fail指针和last指针。
Build函数基本方法是BFS,当前层的结点构造完之后,再检查下一层的点。
初始结点为根节点,把根节点加入队列。根节点的fail指针和last指针均为-1;。
检查队列头的所有儿子,遍历字母集,如果当前结点有为该字母的儿子,则为该儿子结点构造fail和last指针。
如果父亲就是根节点,显然儿子的fail和last都应该指向root。
纪录父亲的fail指针,纪录fail指针为该字母的儿子的结点编号fc(不存在则为-1);在父亲不为根节点的情况下,儿子的fail指针应该指向fc(类似于KMP的next[i+1] = k+1),而last指针则是考虑fc是不是单词结点,如果不是,指向fc的last(类似于next[i+1] = next[k+1])。
如果这个儿子不存在,我们也可以建一个虚拟边,把这个儿子指向fail为这个字母的儿子,这样匹配的之后,就可以自动跳转了。记得检查父亲是不是root,不然会访问下标为-1的地方(所有可能)。
search的时候,相当于匹配,而对于每一个结点,都要回溯一边last指针,找出所有以该结点为单词结尾的模板串。
AC自动机模板题。
AC自动机个人体会:
再了解AC自动机之前,建议先看看KMP和Trie树。
首先看Node结构体内的各个成员所代表的含义:
ch:children缩写,这个结点后的所有儿子。如果串1:abcde的d的编号为4,另外串2:abcdf的d也会编号为4(其实abcd四个都是编号一样的),那么d的儿子有e和f;
fail:该结点失配后,应该跳去下一个匹配的结点的编号。比如abcdf的f失配后,很大可能性跳去e(得看有多少个串了);
last:表示沿着该结点的fail走,遇到的第一个单词结尾的结点。
这里约定好当某结点的失配指针为root时,则下一个字符将会和根节点的儿子们比较(根节点为虚拟结点);当ch[i]为-1时,表示这个儿子不存在。
Insert函数和Trie树中的插入是一样的。
然而重头戏是Build函数,构造fail指针和last指针。
Build函数基本方法是BFS,当前层的结点构造完之后,再检查下一层的点。
初始结点为根节点,把根节点加入队列。根节点的fail指针和last指针均为-1;。
检查队列头的所有儿子,遍历字母集,如果当前结点有为该字母的儿子,则为该儿子结点构造fail和last指针。
如果父亲就是根节点,显然儿子的fail和last都应该指向root。
纪录父亲的fail指针,纪录fail指针为该字母的儿子的结点编号fc(不存在则为-1);在父亲不为根节点的情况下,儿子的fail指针应该指向fc(类似于KMP的next[i+1] = k+1),而last指针则是考虑fc是不是单词结点,如果不是,指向fc的last(类似于next[i+1] = next[k+1])。
如果这个儿子不存在,我们也可以建一个虚拟边,把这个儿子指向fail为这个字母的儿子,这样匹配的之后,就可以自动跳转了。记得检查父亲是不是root,不然会访问下标为-1的地方(所有可能)。
search的时候,相当于匹配,而对于每一个结点,都要回溯一边last指针,找出所有以该结点为单词结尾的模板串。
#include <algorithm> #include <iostream> #include <stdlib.h> #include <string.h> #include <stdio.h> using namespace std; #define MAXK 26 #define MAXN 50010 #define idx(c) (c - 'A') struct Node { int ch[MAXK]; int fail, last, id; void Init() { memset(ch, -1, sizeof(ch)); fail = last = -1; id = 0; } }; struct Trie { Node next[MAXN]; int que[MAXN], head, tail; int cnt[1010]; int root, sz; void Init() { root = sz = 0; next[root].Init(); memset(cnt, 0, sizeof(cnt)); } void Insert(char *s, int k) { int u = root; while(*s) { int c = idx(*s); if(next[u].ch[c] == -1) { next[++sz].Init(); next[u].ch[c] = sz; } u = next[u].ch[c]; s++; } next[u].id = k; } void Build() { int u, ch, f, fc; head = 0, tail = -1; que[++tail] = root; while(head <= tail) { u = que[head++]; for(int i = 0; i < MAXK; i++) { f = next[u].fail; fc = next[f].ch[i]; if(next[u].ch[i] != -1) { ch = next[u].ch[i]; if(u == root) next[ch].fail = next[ch].last = root; else { next[ch].fail = fc; next[ch].last = (next[fc].id ? fc : next[fc].last); if(next[ch].last == -1) next[ch].last = root; } que[++tail] = ch; } else { if(u == root) next[u].ch[i] = root; else next[u].ch[i] = next[f].ch[i]; } } } } void Search(char *s) { int u = root; while(*s) { if(*s >= 'A' && *s <= 'Z') u = next[u].ch[idx(*s)]; else u = -1; if(u == -1) u = root; int tmp = u; while(tmp != root) { if(next[tmp].id) cnt[next[tmp].id]++; tmp = next[tmp].last; } s++; } } }ac; char vir[1010][56]; char web[2000010]; int main() { // freopen("3065.in", "r", stdin); int n; while(~scanf("%d", &n)) { getchar(); ac.Init(); for(int i = 1; i <= n; i++) { // scanf("%s", vir[i]); gets(vir[i]); ac.Insert(vir[i], i); } ac.Build(); // scanf("%s", web); gets(web); ac.Search(web); for(int i = 1; i <= n; i++) if(ac.cnt[i]) printf("%s: %d\n", vir[i], ac.cnt[i]); } return 0; }
相关文章推荐
- HDU 3065 病毒侵袭持续中(AC自动机 数组模板)
- HDU 3065 病毒侵袭持续中(AC自动机模板)
- hdu 3065 病毒侵袭持续中 AC自动机模板题 ,,一A。
- [HDU 3065]病毒侵袭持续中[AC自动机][模板题]
- hdu 3065 病毒侵袭持续中(ac自动机模板题)
- hdu 3065 病毒侵袭持续中 ac自动机模板题
- HDU 3065 AC自动机模板题
- AC自动机 ( 模板题啊 )——病毒侵袭持续中 ( HDU 3065 )
- HDU 3065 病毒侵袭持续中(AC自动机(每个模式串出现次数))
- AC自动机 病毒侵袭持续中 HDU - 3065
- HDU 3065 AC自动机
- hdu 3695 AC自动机模板题
- HDU 3065 病毒侵袭持续中(AC自动机)
- HDU-2896 病毒侵袭 && HDU-3065 病毒侵袭持续中(AC自动机)
- HDU 2222 Keywords Search 【AC自动机模板】
- HDU 3065 AC自动机
- HDU 3065 病毒侵袭持续中(AC自动机)
- HDU 3065 病毒侵袭持续中(AC自动机)
- AC自动机 病毒侵袭持续中 HDU - 3065
- HDOJ 题目3065 病毒侵袭持续中(AC自动机,求字串在母串出现个数)