比较好的 AC自动机算法详解..

【转】http://www.cppblog.com/mythit/archive/2009/04/21/80633.html

个人总结:【图是盗用的..】

ac自动机是用来求出:给出n个单词,和一篇文章arr[],问arr中出现了多少个单词..

第一步:根据给出的n个单词构造一棵字典树

第二步:根据字典树完成失配指针

第三步:枚举文章中的每个字符,并根据拥有了失配指针的字典树 查找 出现的单词个数

以单词:say she shr he her 文章:yasherhs 举例:

第一步:根据给出的n个单词构造一棵字典树

 const int kind = ;
struct node{
node *fail; //失败指针
node *next[kind]; //Tire每个节点的个子节点(最多个字母)
int count; //是否为该单词的最后一个节点
node(){ //构造函数初始化
fail=NULL;
count=;
memset(next,NULL,sizeof(next));
}
}*q[]; //队列,方便用于bfs构造失败指针
char keyword[]; //输入的单词
char str[]; //模式串
int head,tail; //队列的头尾指针

结构体

  void insert(char *str,node *root){
node *p=root;
int i=,index;
while(str[i]){
index=str[i]-'a';
if(p->next[index]==NULL) p->next[index]=new node();
p=p->next[index];
i++;
}
p->count++; //在单词的最后一个节点count+1,代表一个单词
}

构造字典树

第二步:根据字典树完成失配指针

<结果是 (she)每一个字符(s,h,e)都会指向自己上一个字符(root,s,h)的失配指针(root,root,root->h)后的和当前字符匹配((如果没有则指向root)root, root->h, root->h->e)的字符>

即结果是保证树中的节点(node)会指向拥有相同字符串(parents->..->node = root->..->node',parents表示某个祖先节点,node'表示相同字符节点)的枝桠(没有则指向root)

 void build_ac_automation(node *root){
int i;
root->fail=NULL;
q[head++]=root;
while(head!=tail){
node *temp=q[tail++];
node *p=NULL;
for(i=;i<;i++){
if(temp->next[i]!=NULL){
if(temp==root) temp->next[i]->fail=root;
else{
p=temp->fail;
while(p!=NULL){
if(p->next[i]!=NULL){
temp->next[i]->fail=p->next[i];
break;
}
p=p->fail;
}
if(p==NULL) temp->next[i]->fail=root;
}
q[head++]=temp->next[i];
}
}
}
}

完成失配指针

第三步:枚举文章中的每个字符,并根据拥有了失配指针的字典树 查找 出现的单词个数 <cnt += node.cnt>

  int query(node *root){
int i=,cnt=,index,len=strlen(str);
node *p=root;
while(str[i]){
index=str[i]-'a';
while(p->next[index]==NULL && p!=root) p=p->fail;
p=p->next[index];
p=(p==NULL)?root:p;
node *temp=p;
while(temp!=root && temp->count!=-){
cnt+=temp->count;
temp->count=-;
temp=temp->fail;
}
i++;
}
return cnt;
}

查找

查找方法是如果上一个字符的下一个字符和当前字符匹配,则加上node.cnt,并不断按照失配指针查找出现的单词,不断加上node.cnt

失配,则根据失配指针去找可能匹配的出现的单词,找到则加上node.cnt

AC自动机---个人总结的更多相关文章

  1. 基于trie树做一个ac自动机

    基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...

  2. AC自动机-算法详解

    What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...

  3. python爬虫学习(11) —— 也写个AC自动机

    0. 写在前面 本文记录了一个AC自动机的诞生! 之前看过有人用C++写过AC自动机,也有用C#写的,还有一个用nodejs写的.. C# 逆袭--自制日刷千题的AC自动机攻克HDU OJ HDU 自 ...

  4. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2545  Solved: 1419[Submit][Sta ...

  5. BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 3198  Solved: 1532[Submit][Status ...

  6. BZOJ 1212: [HNOI2004]L语言 [AC自动机 DP]

    1212: [HNOI2004]L语言 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1367  Solved: 598[Submit][Status ...

  7. [AC自动机]【学习笔记】

    Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)To ...

  8. AC自动机 HDU 3065

    大概就是裸的AC自动机了 #include<stdio.h> #include<algorithm> #include<string.h> #include< ...

  9. AC自动机 HDU 2896

    n个字串 m个母串 字串在母串中出现几次 #include<stdio.h> #include<algorithm> #include<string.h> #inc ...

  10. 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序

    3881: [Coci2015]Divljak Time Limit: 20 Sec  Memory Limit: 768 MBSubmit: 508  Solved: 158[Submit][Sta ...

随机推荐

  1. C# / MSSQL / WinForm / ASP.NET - SQLHelper中返回SqlDataReader数据

    /// <summary> /// Execute a SqlCommand that returns a resultset against the database specified ...

  2. 一个问题:关于类型转换Type Cast(汇编讲解 as 语法)

    问题如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34   ...

  3. 如何获得getElementById的length这个数值?

    a=document.getElementById("a").innerHTML.length;我觉得你应该这么写 如果是文本框的话document.getElementById( ...

  4. perl EXPORT模块

    Exporter - Implements default import method for modules 实现模块的默认导出方法: 简介: [tomcat@wx03 ~]$ cat hui.pm ...

  5. Ubuntu下安装ADT(图文教程)

    个人感觉Ubuntu下安装ADT跟在Windows大同小异 一.装上JDK和Eclipse 如果还没有装上的,请参考我前面的博文: http://blog.csdn.net/ljphhj/articl ...

  6. JDK1.5后的新特性之一:可变参数

    Java中的可变参数 Java1.5后出现了一个新特性,即可变参数,格式为:类型 …参数 例如: 总的来说,可变参数可以当成是数组来用: public void testSum() { System. ...

  7. 设置静态IP

    设定IP $sudo vi/etc/network/interfaces autolo iface lo inet loopback 加入下面内容 autoeth0 iface eth0inet st ...

  8. FairScheduler的任务调度机制——assignTasks

    首先需要了解FairScheduler是如何在各个Pool之间分配资源,以及每个Pool如何在Job之间分配资源的.FairScheduler的分配资源发生在update()方法中,而该方法由一个线程 ...

  9. java如何运行OS命令(转)

    •javac TestRunTime.java•java TestRunTime hostname // 执行“hostname”Linux命令•即可看到输出 import java.io.IOExc ...

  10. 【Demo 0004】屏幕、窗体及视图基础知识

    本章学习要点       1.  了解iOS中应用程序(UIApplication)与屏幕.窗体以及视图相关基础知识:       2.  掌握应用程序常用的属性与方法:        3.  掌握窗 ...