标签:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222
一个常见的例子就是给出n个单词,再给出一段包含m个字符的文章,让你找出有多少个单词在文章里出现过;
本题就是最基础的模板;在此之前需要理解kmp和字典树(trie);
Trie树有3个基本性质:
(1) 根节点不包含字符,除根节点外每一个节点都只包含一个字符;
(2) 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串;
(3) 每个节点的所有子节点包含的字符都不相同。
构造失败指针的过程概括起来就一句话:设这个节点上的字母为x,沿着他父亲的失败指针走,
直到走到一个节点,他的儿子中也有字母为x的节点。然后把当前节点的失败指针指向那个字符
也为x的儿子。如果一直走到了root都没找到,那就把失败指针指向root。
1: root的子节点的失败指针都指向root。
2: 节点(字符为x)的失败指针指向:从X节点的父节点的fail节点回溯直到找到某节点的子节点也是字符x,没有找到就指向root。
从root节点开始,每次根据读入的字符沿着自动机向下移动。 当读入的字符,在分支中不存在时,递归走失败路径。
如果走失败路径走到了root节点, 则跳过该字符,处理下一个字符。 因为AC自动机是沿着输入文本的最长后缀移
动的,所以在读取完所有输入文本后,最后递归走失败路径,直到到达根节点, 这样可以检测出所有的模式。
搜索的步骤:
从根节点开始一次搜索;
取得要查找关键词的第一个字符,并根据该字符选择对应的子树并转到该子树继续进行检索;
在相应的子树上,取得要查找关键词的第二个字符,并进一步选择对应的子树进行检索。
迭代过程……
在某个节点处,关键词的所有字符已被取出,则读取附在该节点上的信息,即完成查找。
匹配模式串中出现的单词。当我们的模式串在Trie上进行匹配时,如果与当前节点的关键字不能继续匹配的时候,
就应该去当前节点的失败指针所指向的节点继续进行匹配。
匹配过程出现两种情况:
当前字符匹配,表示从当前节点沿着树边有一条路径可以到达目标字符, 此时只需沿该路径走向下一个节点继续匹配即可 ,目标字符串指针移向下个字符继续匹配;
当前字符不匹配,则去当前节点失败指针所指向的字符继续匹配,匹配过程随着指针指向root结束。
重复这2个过程中的任意一个,直到模式串走到结尾为止。
哎,看了大神的讲解:不会AC自动机基础的可以参考一下:
#include<stdio.h> #include<string.h> #include<algorithm> #include<queue> using namespace std; const int N = 1e6+7; char MumStr[N]; struct node { node *next[26], *fail; int leaf; }; void AddTrie(char s[], node *head) { node *p = head; for(int i=0; s[i]; i++) { int k = s[i] - ‘a‘; if(p->next[k] == NULL) p->next[k] = new node(); p = p->next[k]; } p->leaf ++; } void GetFail(node *head) { queue<node*>Q; Q.push(head); while(Q.size()) { node *p = Q.front(); Q.pop(); for(int i=0; i<26; i++) { if(p->next[i] != NULL) { node *t = p->fail; while(t != NULL) { if(t->next[i] != NULL) { p->next[i]->fail = t->next[i]; break; } t = t->fail; } if(t == NULL) p->next[i]->fail = head; Q.push(p->next[i]); } } } } int Query(node *head) { int sum = 0; node *p = head; for(int i=0; MumStr[i]; i++) { int k = MumStr[i] - ‘a‘; while(p->next[k] == NULL && p != head) p = p->fail; if(p->next[k] == NULL) continue; node *t = p = p->next[k]; while(t!=head && t->leaf != -1) { sum += t->leaf; t->leaf = -1; t = t->fail; } } return sum; } int main() { int T, n; char s[110]; scanf("%d", &T); while(T--) { node *head = new node(); scanf("%d", &n); for(int i=0; i<n; i++) { scanf("%s", s); AddTrie(s, head); } GetFail(head); scanf("%s", MumStr); int ans = Query(head); printf("%d\n", ans); } return 0; }
Keywords Search---hdu2222(AC自动机 模板)
标签:
原文地址:http://www.cnblogs.com/zhengguiping--9876/p/4854752.html