// 此博文为迁移而来,写于2015年5月27日,不代表本人现在的观点与看法。原始地址:http://blog.sina.com.cn/s/blog_6022c4720102w1s8.html

1、前言
       怪我咯,因为Trie树和AC自动机的密切相关,我想一起讲完哈哈。。。看过前面博文的同学应该都知道了,AC自动机其实就是相当于在Trie树上跑KMP。
       
2、Trie树
       Trie树,就是字母树。Trie树是多叉树,每个节点为一个字母。其根节点为象征节点(就是说没有含义,但是存在这个节点),从根节点开始建立,每个节点至多为26个子节点(不要我说为什么吧),这样,我们就可以用这种方便快捷的方式存储字符串。其应用也不言而喻,用于保存,统计,排序,查找大量字符串。因为很简单,我们不讲太多,根据图像,自己造几个字符串,慢慢理解,看看代码,一下就懂了。

       如图所示,该字符串保存了say,she,shr,her四个字符串。有个小小的问题:在建树的时候,我们注意到最坏情况可能为二十六叉树,空间复杂度可想而知。所以,如果用指针可能更省空间。
 
3、构造fail指针(KMP)
       在网上看到有许多AC自动机的算法分析,但是发现好像都很相似(莫非都是Ctrl+C/V)。构造fail指针,使当前字符失配时跳转到具有最长公共前后缀的字符继续匹配。如同 KMP算法一样, AC自动机在匹配时如果当前字符匹配失败,那么利用fail指针进行跳转。由此可知如果跳转,跳转后的串的前缀,必为跳转前的模式串的后缀。并且跳转的新位置的深度(匹配字符个数)一定小于跳之前的节点。
       我们在构建好Trie树之后,可以利用BFS进行 fail指针求解。我们最开始先将root节点入队,因为第一个字符不匹配需要重新匹配,所以第一个字符都指向root。这样,我们得到下图:

3、例题
Keywords Search [ HDU 2222 ]
       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, the system will match the keywords with description of image and show the image which the most keywords be matched.
      To simplify the problem, giving you a description of image, and some keywords, you should tell me how many keywords will be match. (well, it's about time to exercise your English !)
 
输入格式
       First line will contain one integer means how many cases will follow by.
       Each case will contain two integers N means the number of keywords and N keywords follow. (N <= 10000)
       Each keyword will only contains characters 'a'-'z', and the length will be not longer than 50.
       The last line is the description, and the length will be not longer than 1000000.
 
输出格式
       Print how many keywords are contained in the description.
 
输入样例
1
5
she
he
say
shr
her
yasherhs
 
输出样例
3
 
Code:
-----------------------------------------------------------------------------------------------------
#include<cstdio>
#include<cstring>
#define MAXN 105
#define MAXM 1000005
 
struct Node
{
        int next[30],x,fail,num,count;
};
Node tree[MAXM];
 
int n,tot,nowLen,root,t,q[MAXM];
char article[MAXM],word[MAXN];
 
void insert()
{
        int temp,now=root,len=strlen(word); 
        for (int i=0;i<=len-1;i++)
        {
                temp=word[i]-'a';
                if (tree[now].next[temp]==0) { tot++; tree[now].next[temp]=tot; }
                now=tree[now].next[temp];
        }  
        tree[now].count++;
}
 
void getFail()
{
        int head=1,tail=2;
        q[1]=root;
        while (head!=tail)
        {
                for (int i=0;i<=25;i++)
                {
                        int next=tree[q[head]].next[i];
                        if (next!=0)
                        {
                                if (q[head]==root) tree[next].fail=root;
                                else
                                {
                                        int temp=tree[q[head]].fail;
                                        while (temp!=0)
                                        {
                                                if (tree[temp].next[i]!=0)
                                                {
                                                        tree[next].fail=tree[temp].next[i];
                                                        break;
                                                }
                                                temp=tree[temp].fail;
                                        }
                                        if (temp==0) tree[next].fail=root;
                                }
                                q[tail++]=next;
                        }
                } 
                head++;
        }
}
 
int find()
{
        int len=strlen(article),ans=0,n1=root;
        for (int i=0;i<=len-1;i++)
        {
                int now=article[i]-'a';
                while (tree[n1].next[now]==0 && n1!=root) n1=tree[n1].fail;
                n1=tree[n1].next[now];
                if (n1==0) n1=root;
                int n2=n1;
                while (n2!=root && tree[n2].count!=-1)
                {
                        ans+=tree[n2].count;
                        tree[n2].count=-1;
                        n2=tree[n2].fail;
                }
        }
        return ans;
}
 
int main()
{
        freopen("AC.in","r",stdin);
        freopen("AC.out","w",stdout);
        scanf("%d",&t); 
        for (int j=1;j<=t;j++)
        {
                scanf("%d",&n);
                root=tot+1; tot++;
                for (int i=1;i<=n;i++) 
                {
                        scanf("%s",word); nowLen=strlen(word)-1;
                        insert();
                }
                getFail(); for (int i=root+1;i<=tot;i++) if (tree[i].fail==0) tree[i].fail=root;
                scanf("%s",article);
                printf("%d\n",find());
        }
        return 0;
-----------------------------------------------------------------------------------------------------

[知识点]Trie树和AC自动机的更多相关文章

  1. 算法笔记--字典树(trie 树)&& ac自动机 && 可持久化trie

    字典树 简介:字典树,又称单词查找树,Trie树,是一种树形结构,是哈希树的变种. 优点:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较. 性质:根节点不包含字符,除根节点外每一个 ...

  2. [HNOI2004]L语言 trie树? Ac自动机? hash!!

    题目描述 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写字母构成.一个单词W也是由若干小写字母构成.一个字典D是若干个单词的 ...

  3. Trie树&kmp&AC自动机&后缀数组&Manacher

    Trie 计数+Trie,读清题意很重要 https://vjudge.net/problem/UVALive-5913 kmp AC自动机 模板:https://vjudge.net/problem ...

  4. 从Trie谈到AC自动机

    ZJOI的SAM让我深受打击,WJZ大神怒D陈老师之T3是SAM裸题orz...我还怎么混?暂且写篇`从Trie谈到AC自动机`骗骗经验. Trie Trie是一种好玩的数据结构.它的每个结点存的是字 ...

  5. HDU 5384 字典树、AC自动机

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5384 用字典树.AC自动机两种做法都可以做 #include<stdio.h> #includ ...

  6. 中文分词系列(二) 基于双数组Tire树的AC自动机

    秉着能偷懒就偷懒的精神,关于AC自动机本来不想看的,但是HanLp的源码中用户自定义词典的识别是用的AC自动机实现的.唉-没办法,还是看看吧 AC自动机理论 Aho Corasick自动机,简称AC自 ...

  7. 【AC自动机】【字符串】【字典树】AC自动机 学习笔记

    blog:www.wjyyy.top     AC自动机是一种毒瘤的方便的多模式串匹配算法.基于字典树,用到了类似KMP的思维.     AC自动机与KMP不同的是,AC自动机可以同时匹配多个模式串, ...

  8. Trie图(AC自动机)总结

    AC自动机构建完成后,某个节点沿着Fail链向上能从长到短走到自己的所有后缀.一般的,遍历主串进行匹配,就是在Trie图上定向移动的过程. 构造(一遍 BFS) void build_AC() { ; ...

  9. 【uva1502/hdu4117-GRE Words】DP+线段树优化+AC自动机

    这题我的代码在hdu上AC,在uva上WA. 题意:按顺序输入n个串以及它的权值di,要求在其中选取一些串,前一个必须是后一个的子串.问d值的和最大是多少. (1≤n≤2×10^4 ,串的总长度< ...

随机推荐

  1. Kl 证明 凸函数

    回到随机变量传输问题,假设传输中我们不知道具体 分布情况(unknown),我们用一个已知的分布 ,来模拟它,那么在这种情况下如果我们利用 尽可能高效的编码,那么我们平均需要多少额外的信息量来描述x呢 ...

  2. vim、gvim加载文件慢

    1. strace -f -T -o vim.strace vim 2. vim --startuptime "vim-time.txt" 3. gvim -f

  3. oracle 11g r1 RAC增加新节点

    在一套两节点的rac上增加一个新的节点,详细的操作记录如下:   已有节点RAC1,RAC2 一,环境及版本: 公司环境:Vmware Esxi 5.5  操作系统:Redhat 5.8 x86_64 ...

  4. hdu 4045 2011北京赛区网络赛F 组合数+斯特林数 ***

    插板法基础知识 斯特林数见百科 #include<iostream> #include<cmath> #include<cstdio> #include<cs ...

  5. ZLL本地局域网通信过程

    Interface_srpcserver -----以灯的状态操作位例 网关与客户端通过Socket API通信,Socket API在socket_server.c中实现,socket_server ...

  6. Error: Could not find or load main class test.EditFile

    今天写了一个简单的小程序,运行之后发现Error: Could not find or load main class test.EditFile,项目无法启动.删除main中的所有内容之后依旧提示该 ...

  7. Java学习笔记(七)——对象

    一.类与对象 1.类的定义 类就是模型,确定对象将会拥有的特征(属性)和行为(方法). 2.类的特点 (1)类是对象的类型 (2)具有相同属性和方法的一组对象的集合. 3.对象的属性: 对象具有的各种 ...

  8. 【项目经验】——JSON.parse() && JSON.stringify()

    我们在做项目的时候,都知道序列化和反序列化,师哥说:"有正就有反,有来就有回!"的确,就是这样.然后我们在这里分享一下JSON.stringify()  和JSON.parse() ...

  9. 【myEcplise2015 更换主题+字体颜色】

    更换myEcplise样式: 若对js文件或者java文件中的字体颜色不是很满意,可以去按照这个路径去更新字体颜色: 以javaScript文件为例子: 修改完成之后,javascript文件中文字是 ...

  10. Codeforces Round #354 (Div. 2)-C

    C. Vasya and String 题目链接:http://codeforces.com/contest/676/problem/C High school student Vasya got a ...