// 此博文为迁移而来,写于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. Qt Designer怎样加入资源文件

    Qt Designer中如果在设计UI界面的时候要加入一些图素,图标等资源的时候是不能直接添加进去的,需要在Qt开发目录下编写QRC文件 qrc文件格式如下: <RCC> <qres ...

  2. BI 项目管理之角色和职责

          DW/BI 系统在生命周期中需要许多不同的角色和技能,它们来自业务和技术领域.本文将介绍创建DW/BI 系统所涉及的主要角色.角色和人之间很少是一对一关系.与我们合作的团队小到只有一人,大 ...

  3. WPF QuickStart系列之样式和模板(Style and Template)

    在WPF桌面程序中,当我们想构建一个统一的UI表现时(在不同操作系统下,显示效果一致),此时我们就需要使用到WPF中的样式和模板技术.简单来说,如果我们需要简单的给一个Button设置宽,高,Marg ...

  4. [荐]js模版引擎handlebars.js

    [官方介绍:http://handlebarsjs.com/] Handlebars provides the power necessary to let you build semantic te ...

  5. Sublime Text 3 安装Go语言相关插件gosublime

    1.打开Sublime Text,使用快捷键 ctrl+` (左上角Tab键上方,Esc键下方)或者使用菜单 View > Show Console menu,此时将出现Sublime Text ...

  6. SGU 275 To xor or not to xor 高斯消元求N个数中选择任意数XORmax

    275. To xor or not to xor   The sequence of non-negative integers A1, A2, ..., AN is given. You are ...

  7. MySQL5.7中新增的JSON类型的使用方法

    创建表json_test: CREATE TABLE json_test(id INT(11) AUTO_INCREMENT PRIMARY KEY,person_desc JSON)ENGINE I ...

  8. 已解决:Strict Standards: Non-static method cls_image::gd_version() should not be called statically in...

    在安装Ecshop的时候,遇到两个⚠️问题: Strict Standards: Non-static method cls_image::gd_version() should not be cal ...

  9. OpenGL大作业

    GLfloat light0_position[] = { 15.0,15.0,15.0,10.0 };//定义光源位置 103glLightfv(GL_LIGHT0, GL_POSITION, li ...

  10. Angular JS学习之指令

    1.Angular JS通过称为指令的新属性来扩展HTML:通过内置的指令来为应用添加功能: 2.AngularJS指令:AngularJS指令是扩展的HTML属性,带有前缀ng-: **ng-app ...