ac自动机基本

  今天研究了一下ac自动机,感觉学了些入门的知识,什么可持久化自动机、有限状态自动机,还有自动机上的DP还不是很懂。所以今天先贴基本代码,以后补充其他知识。

  参考资料:http://blog.csdn.net/niushuai666/article/details/7002823。里面介绍很详细了,特别是构造fail指针那幅图特别经典。注意到KMP的有两种写法:第i位fail指针指向前面某个具有相同元素的最近位置j;或第i位fail指针指向前面最近的具有不同元素的位置j,但要求i-1与j-1元素相同。(两种KMP匹配时稍有差异,第一种会好处理,第二种速度更快因为避免了很多重复但匹配不到的情况)。而ac自动机虽基于KMP,但一般会写第一种即fail指向元素相同而非不同的位置(那幅图明显体现了),至于为什么,第二种不好处理我也不大会写orz。

  直接上代码,功能的是判断若干个给定字符串是否在字符串str中出现过。

  

 1 #include<iostream>
 2 #include<string.h>
 3 #include<queue>
 4 using namespace std;
 5
 6 struct trie_node
 7 {
 8     trie_node *fa,*next[26],*fail;
 9     char cc;
10     bool end;
11 }*root;
12
13 void mdy(trie_node* now,trie_node* fa,char cc)//mordify
14 {
15     long i;
16     now->fa=fa;
17     for (i=0;i<26;i++)now->next[i]=NULL;
18     now->cc=cc;
19     now->end=false;
20 }
21
22 void update(string ss,trie_node* now)//insert strings into Trie
23 {
24     char cc;
25     cc=ss[0];
26     if (now->next[cc-‘a‘]==NULL){
27         now->next[cc-‘a‘]=new trie_node;
28         mdy(now->next[cc-‘a‘],now,cc);
29     }
30     if (ss.length()==1){
31         now->next[cc-‘a‘]->end=true;
32         return;
33     } else update(ss.substr(1),now->next[cc-‘a‘]);
34 }
35
36 void build_fail()//BFS
37 {
38     queue<trie_node*>v;
39     trie_node *fail,*now;
40     long i;
41     char cc;
42     v.push(root);
43     while (!v.empty()){
44         now=v.front();
45         v.pop();
46         fail=now->fa->fail,cc=now->cc;
47         while (fail!=NULL){
48             if (fail->next[cc-‘a‘]!=NULL){
49                 fail=fail->next[cc-‘a‘];
50                 break;
51             } else fail=fail->fail;
52         }
53         if (fail==NULL)fail=root;
54         now->fail=fail;
55         for (i=0;i<26;i++)if (now->next[i]!=NULL)v.push(now->next[i]);
56     }//root‘s fail->root
57 }
58
59 bool ac_automachine(string str)//matching,to find if those string in trie have appeared in str(also you can change into different function)
60 {
61     trie_node* now;
62     long i;
63     char cc;
64     now=root;
65     for (i=0;i<str.length();i++){
66         cc=str[i];
67         while (now!=NULL)
68             if (now->next[cc-‘a‘]!=NULL){
69                 now=now->next[cc-‘a‘];
70                 break;
71             } else now=now->fail;
72         if (now==NULL)now=root;
73             else if (now->end)return true;
74     }
75     return false;
76 }
77
78 int main()
79 {
80     string s1,str;
81     long n,i;
82     cin>>n;
83     mdy(root,NULL,‘ ‘);
84     for (i=1;i<=n;i++){
85         cin>>s1;
86         update(s1,root);
87     }
88     build_fail();
89     cin>>str;
90     if (ac_automachine(str))cout<<"YES there is."<<endl;
91         else cout<<"NO there isn‘t."<<endl;
92     return 0;
93 }

ac_automachine

时间: 2024-11-08 22:11:01

ac自动机基本的相关文章

暑假集训day9补充(AC自动机)

推荐网站http://blog.csdn.net/niushuai666/article/details/7002823 AC自动机嘛,此AC(aho-corasick)非彼AC(Accepted). 我也不是很会解释 有一题是必须打的hdu2222. #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int mn=

ac自动机基础模板(hdu2222)

In the modern time, Search engine came into the life of everybody like Google, Baidu, etc. Wiskey also wants to bring this feature to his image retrieval system. Every image have a long description, when users type some keywords to find the image, th

HDU 2825 Wireless Password AC自动机+dp

训练赛第二场的I题,上完体育课回来就把这题过了,今天训练赛rank1了,还把大大队虐了,而且我还过了这道题 (虽然我也就过了这道题...),第一次在比赛中手写AC自动机还带dp的,心情大好. 给一个字符串集合,求包含该集合超过K个字符的,长度为L的字符串的个数. 显然是在AC自动机上跑dp,设dp[u][L][k]表示当前在结点u,还要走L步,当前状态为k的个数.一开始第三维表示的是包含k个字符串,但是题目要求不含重复的,那就只能状压了.转移为dp[u][L][k]+=dp[v][L-1][nk

HDU 2896-病毒侵袭(ac自动机)

题意: 给定多个模式串,每给一个母串,输出包含模式串的编号,最后输出包含模式串的母串的数量. 分析: ac自动机模板 #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <st

hdu2222 Keywords Search &amp; AC自动机学习小结

传送门:http://http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路:AC自动机入门题,直接上AC自动机即可. 对于构建AC自动机,我们要做的只有三件事: 1)构建字典树 2)构建失败指针 3)构建trie图(这道题好像不做这一步也能A...但是这一步不做是会被卡成O(n^2)的...) 1)第一步还是比较好理解的 根是虚根,边代表字母,那么根到终止节点的路径就是一个字符串,这样对于前缀相同的字符串我们就可以省下存公共前缀的空间. 加入一个模式

hdoj 2896 病毒侵袭(AC自动机)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896 思路分析:题目为模式匹配问题,对于一个给定的字符串,判断能匹配多少个模式:该问题需要静态建树,另外需要对AC自动机的模板加以修改, 对于每个匹配的模式的最后一个单词的fail指针指向root,即可实现一个字符串进行多次模式匹配: 代码如下: #include <queue> #include <cstdio> #include <cstring> #include &

从Trie谈到AC自动机

ZJOI的SAM让我深受打击,WJZ大神怒D陈老师之T3是SAM裸题orz...我还怎么混?暂且写篇`从Trie谈到AC自动机`骗骗经验. Trie Trie是一种好玩的数据结构.它的每个结点存的是字母,因此得名`字母树`. 出一张图让大家感受下. (image powered by SaiBu NaoCu) 上面那是一棵插入了 ape,app,applicant,application,bake,ban,banana 等词的Trie.红色结点表示接受态. 显然,查找时只需顺着链照下来,插入只需

AC自动机

AC自动机 直接学AC自动机比较难理解,强烈建议先学完KMP和字典树并进行一定的练习后,对于失配指针和字典树构造有一定理解后再来学AC自动机的内容.有关AC自动机的详细介绍可见刘汝佳的<算法竞赛入门经典训练指南>P214. 给你一个字典(包含n个不重复的单词),然后给你一串连续的字符串文本(长为len),问你该文本里面的哪些位置正好出现了字典中的某一个或某几个单词?输出这些位置以及出现的单词. 这个问题可以用n个单词的n次KMP算法来做(效率为O(n*len*单词平均长度)),也可以用1个字典

【POJ3208】传说中POJ最难的数位DP?(正解AC自动机,二解数位DP,吾异与之)

题意: 多组数据,每组求第n个包含'666'的数(不能断开),如1:666,2:1666,14:6667. 题解: AC自动机解法没去想,数位DP没学,这里有一种类似于数位DP,却又与数位DP不同,我称为数位树. 数位树: 将数n如线段树一样地拆分成多个小段,进行递归处理得出答案. 本题详(lue)解: 直接看每一位应该是什么数,然后n减去相应的数,使得在下一层转换为子问题"在开头有b个连续的6时,求第a个带'666'的数".就是如此简单,如此简单!!!! 代码来啦! #include

跳跃表,字典树(单词查找树,Trie树),后缀树,KMP算法,AC 自动机相关算法原理详细汇总

第一部分:跳跃表 本文将总结一种数据结构:跳跃表.前半部分跳跃表性质和操作的介绍直接摘自<让算法的效率跳起来--浅谈"跳跃表"的相关操作及其应用>上海市华东师范大学第二附属中学 魏冉.之后将附上跳跃表的源代码,以及本人对其的了解.难免有错误之处,希望指正,共同进步.谢谢. 跳跃表(Skip List)是1987年才诞生的一种崭新的数据结构,它在进行查找.插入.删除等操作时的期望时间复杂度均为O(logn),有着近乎替代平衡树的本领.而且最重要的一点,就是它的编程复杂度较同类