Aho-Corasick算法

100种算法【Python版】第17篇——Aho-Corasick算法 阅读详情
1、概述

Aho-Corasick自动机算法(简称AC自动机)1975年产生于贝尔实验室。该算法应用有限自动机巧妙地将字符比较转化为了状态转移。此算法有两个特点,一个是扫描文本时完全不需要回溯,另一个是时间复杂度为O(n),时间复杂度与关键字的数目和长度无关。

好了,我们先看下最原始的多模式匹配算法:

主串T,n=strlen(T)。

模式串Pi mi = strlen(pi)

  1. for(i=0;i<n-MIN(m);++i)
  2. for(j=0;j<k;++j)
  3. if(n-mk<=n-i &&memcmp(T[i],Pk,mk)==0)
  4. printf(“match/n”);

  1. for(i=0;i<n-MIN(m);++i)
  2. for(j=0;j<k;++j)
  3. if(n-mk<=n-i &&memcmp(T[i],Pk,mk)==0)
  4. printf(“match/n”);

是O(mn)的时间复杂度。

上面的算法很笨吧,下面看看聪明的AC算法是个啥意思。

2、 AC算法思想

AC算法思想:用多模式串建立一个确定性的树形有限状态机,以主串作为该有限状态机的输入,使状态机进行状态的转换,当到达某些特定的状态时,说明发生模式匹配。

下图是多模式he/ she/ his /hers构成的一个确定性有限状态机,做几点说明:

wps_clip_image-531

1、 该状态机优先按照实线标注的状态转换路径进行转换,当所有实线标注的状态转换路径条件不能满足时,按照虚线的状态转换路径进行状态转换。如:状态0时,当输入h,则转换到状态1;输入s,则转换到状态3;否则转换到状态0。

2、 匹配过程如下:从状态0开始进行状态转换,主串作为输入。如主串为:ushers,状态转换的过程是这样的:

wps_clip_image-720

3、 当状态转移到2,5,7,9等红色状态点时,说明发生了模式匹配。

如主串为:ushers,则在状态5、2、9等状态时发生模式匹配,匹配的模 式串有she、he、hers。

定义:

在预处理阶段,AC自动机算法建立了三个函数,转向函数goto,失效函数failure和输出函数output,由此构造了一个树型有限自动机。

转向函数,指的是一种状态之间的转向关系。g(pre, x)=next:状态pre在输入一个字符x后转换为状态next(上图中的实线部分)。如果在模式串中不存在这样的转换,则next=failstate。

失效函数, 指的也是状态和状态之间一种转向关系。f(per)=next:是在比较失配的情况下使用的转换关系。在构造转向函数时,把不存在的转换用failstate表示,但是failstate不是一个具体的状态,状态机转换转换到failstate状态的时候就不知道该往哪转了。所以就要在状态 机中找到一个有意义的状态代替failstate,当出现failstate状态时,自动切换到那个状态。

这个状态节点应该具有这样的特征:从这个状态节点向上直到树根节点(状态0)所 经历的输入字符,和从产生failstate状态的那个状态节点向上所经历的输入字符串完全相同。而且这个状态节点,是所有具备这些条件的节点中深度最小 的那个节点。如果不存在满足条件的状态节点,则失效函数为0。

累死了。举例子说吧,对状态9输入任何一个字符都会产生failstate状态,需要失效函数。状态3向上到状态0经过的输入字符串为s;而由状态9向上的输入字符串为sreh。字符串s相同,并且状态3是满足此条件的唯一节点,则

f(9)=3。

说来说去,失效函数就是要干这么件事儿:

wps_clip_image-1497

意思就是说,在比较模式串1发生失配时,找一个模式串2,使得P2[0...j-1] = P1[i-j+1...i]。然后继续比较模式串2。看上面那个图,想起点儿什么东西没有?对了,是KMP算法。有人说AC算法就是KMP算法在多模式匹配情况下的扩展。


输出函数
,指的是状态和模式串之间的一种关系。output(i)={P},表示当状
态机到达状态i时,模式串集合{P}中的所有模式串可能已经完成匹配。

例:

模式串为:he/ she/ hers/ his 时,如上图所示:

转向函数:

wps_clip_image-1758

失效函数:

wps_clip_image-1780

输出函数:

wps_clip_image-1801

3、 AC代码分析

下面的代码参考snort入侵检测系统开源软件的acsmx.c文件。

3.1数据结构分析

所有状态都被存储在一个ACSM_STATETABLE类型的数组中。

typedef struct {

int NextState[ ALPHABET_SIZE ];

int FailState;

ACSM_PATTERN *MatchList;

}ACSM_STATETABLE;

NextState对应转向函数;FailState对应失效函数;MatchList对应输入函数。

3.2代码分析

代码流程如下图:

wps_clip_image-2124

 

/* 
 ac算法的实现 
*/ 
 
#include  
#include  
#include  
using namespace std; 
 
#define MAX_STATE 100   //自动机最大状态数 
#define MAX_SYMBOL 256   //匹配的字符数 可以匹配所有的ASCII码 
#define MAX_MODE 20   //最大模式串数 
 
int GoAndFail[MAX_STATE][MAX_SYMBOL];   //状态转移表--DFA 包括转向函数和失效函数 
int F[MAX_STATE] ; 
int output[MAX_STATE];  //在该状态的输出模式串 -1表示没有输出 
 
unsigned int statecount; //总状态数-1 
unsigned int modecount;  //模式串数-1 
 
struct mode{ 
 unsigned int statenum;  //模式串数 
 string modestring[MAX_MODE];  //在该状态时匹配的模式串 
}match[MAX_MODE]; 
 
void init() 
{//初始化全局变量 
 int i,j; 
 statecount = 1; 
 modecount = 0; 
 for (i = 0 ; i < MAX_MODE; i++ ) 
 { 
  match[i].statenum = 0; 
  for (j = 0 ; j < MAX_MODE; j++) 
  { 
   match[i].modestring[j] = ""; 
  } 
 } 
 for (i = 0 ; i < MAX_STATE; i++) 
 { 
  output[i] = -1; 
  F[i] = 0; 
  for (j = 0 ; j < MAX_SYMBOL; j++) 
  { 
   GoAndFail[i][j] = 0; 
  }   
 } 
} 
 
void go() 
{ 
 u_int c; 
 u_int currentstate ; 
 string str = "" ;  //当前模式串 
 bool start = true; 
 
 //获取输入并得到转向函数G 
 printf("请输入模式串集(允许中文 以空格分隔每个串,以回车结束):"); 
 while((c = getchar()) != (u_int)'/n') 
 { 
  if (c != (u_int)' ') 
  { 
   if (start) 
   { 
    start = false; 
    modecount ++; 
    currentstate = 0; 
    str = ""; 
   } 
   str += c; 
   if(GoAndFail[currentstate][c] == 0) 
   { 
    GoAndFail[currentstate][c] = statecount ; 
    currentstate = statecount; 
    statecount ++; 
   } 
   else 
    currentstate = GoAndFail[currentstate][c]; 
 
  }  
  else 
  { 
   match[modecount].statenum = 1; 
   match[modecount].modestring[0] = str; 
   output[currentstate] = modecount; 
   start = true; 
   if (modecount == MAX_MODE) 
   { 
    printf("允许输入的最多模式串数为 %d",MAX_MODE);  
    goto END; 
   } 
  } 
 } 
 match[modecount].statenum = 1; 
 match[modecount].modestring[0] = str; 
 output[currentstate] = modecount; 
 
  
 return; 
END: 
 printf("Press any key to continue..."); 
 c = getch(); 
 return; 
 
} 
 
void addOutPut(u_int sstate,u_int dstate) 
{//把sstate状态的输出集添加到dstate状态的输出集中 
 
 int s = output[sstate];  
 int d = output[dstate]; 
 u_int k; 
 if ( s >= 0 && d >= 0) 
 { 
  for (k = 0 ; k < match[s].statenum ; k++) 
  {//将输出集s添加到输出集d中结尾,这里没有考虑如果两个输出集有相同元素的情况 
   match[d].modestring[match[d].statenum] = match[s].modestring[k]; 
   match[d].statenum++; 
  } 
 } 
 else if (s >= 0 && d < 0) 
 { 
  output[dstate] = s; 
 }     
} 
void fail() 
{ 
 u_int i,j,t; 
 //以下为求失效函数F 
 for(i = 1 ; i < statecount; i++) 
 { 
  for (j = 0 ; j < MAX_SYMBOL; j++) 
  { 
   t = GoAndFail[i][j]; 
   if ( t!= 0) 
   { 
    F[t] = GoAndFail[F[i]][j]; 
    addOutPut(F[t], t); 
   } 
  } 
 } 
 //打印失效数F 
 /*for (i = 0 ; i < statecount; i++) 
 { 
  printf("F(%u) = %u/n", i,F[i]); 
 } 
*/ 
 //打印输出集 
 for (i = 0  ; i < statecount; i++) 
 { 
  if (output[i] != -1) 
  { 
   for (j = 0 ; j < match[output[i]].statenum; j++) 
   { 
    printf("Output(%u) = %s/n",i,&match[output[i]].modestring[j][0]); 
    //cout 
   } 
  }   
 } 
} 
 
void prec() 
{//预处理阶段 
 u_int currentstate = 1; 
 //u_short i; 
 
 //初始化变量 
 init(); 
 //建立转向函数 
 go(); 
 //建立失效函数 
 fail(); 
 
} 
 
bool AC(u_char c,bool rst) 
{ 
 static u_int currentstate = 0; 
 u_int state; 
 u_int j; 
 if (rst) 
 {//复位 重新开始匹配 
  currentstate = 0; 
 } 
 
 if (c < MAX_SYMBOL) 
 { 
  state = GoAndFail[currentstate][c]; 
  if (state == 0) 
  { 
   currentstate = GoAndFail[F[currentstate]][c]; 
  } 
  else 
  { 
   currentstate = state;  
  }  
 
  if (output[currentstate] != -1) 
  { 
   for (j = 0 ; j < match[output[currentstate]].statenum; j++) 
   { 
    printf("Match string with %s/n", &match[output[currentstate]].modestring[j][0]); 
     
    return true; 
   } 
  } 
 } 
 return false; 
 
} 
 
void test_of_AC() 
{ 
 u_char c; 
 printf("请输入需要匹配的字符串:"); 
 while ((c = getchar()) != (u_int)'/n') 
 { 
  AC(c,false);   
 } 
   
 
}


深入理解Aho-Corasick字符串匹配算法 Aho-Corasick算法是一种多模式串匹配算法,广泛应用于文本搜索、字符串匹配等领域。它由贝尔实验室的Alfred V. Aho和Margaret J. Corasick于1975年提出,旨在高效率地在给定文本中查找多个模式串的出现位置。前缀函数定义为对于AC自动机中的每个节点,表示从根节点开始到该节点的所有路径上的字符形成的子串集合中,最长相同后缀的长度。这个函数使得算法在遇到不匹配的情况时,可以快速跳转到最近的可能匹配位置,而不是从头开始,大大提高了匹配效率。 阅读详情

相关推荐

AC自动机算法(Aho-Corasick 多模式匹配算法)

AC自动机算法(Aho-Corasick 多模式匹配算法)C#实现

【算法】Aho-Corasick多模式匹配算法

AC算法实现和匹配

zoetu 2807

信创改造实战:SpringBoot项目迁移到宝兰德BES 9.5.5的完整避坑指南(附依赖与web.xml配置)

本文详细介绍了将SpringBoot项目迁移到宝兰德BES 9.5.5的完整流程,包括依赖改造、web.xml配置降级等关键步骤。通过实战案例和避坑指南,帮助开发者高效完成国产中间件适配,确保项目平稳运行。特别针对Tomcat依赖排除和BES适配器选择提供了专业建议。

weixin_30689307的博客 735

Aho-Corasick 多模式匹配算法(AC自动机)

一、概述 Aho-Corasick算法是多模式匹配中的经典算法,目前在实际应用中较多。 Aho-Corasick算法对应的数据结构是Aho-Corasick自动机,简称AC自动机。 搞编程的一般都应该知道自动机FA吧,具体细分为:确定性有限状态自动机(DFA)和非确定性有限状态自动机NFA。普通的自动机不能进行多模式匹配,AC自动机增加了失败转移,转移到已经输入成功的文本的后缀,来实现。 在学习AC自动机之前我们必须要学习一下KMP算法和Trie树(字典树) KMP算法:http://www.active

qigaohua的博客 2548

跨越移植陷阱:ESP-IDF下LVGL与ILI9341的组件化集成与常见避坑指南

本文详细解析了在ESP-IDF环境下将LVGL图形库与ILI9341显示屏驱动进行组件化集成的完整流程。重点介绍了移植过程中的关键配置策略、内存管理优化技巧以及常见问题解决方案,帮助开发者有效规避内存溢出、显示异常等典型陷阱,实现高效稳定的嵌入式GUI开发。

yhn456789的博客 623

SAP VC实战:用CU01和CS02搞定BOM里的‘智能’对象相关性(附语法避坑指南)

在工业制造领域,产品配置的复杂性往往超出想象。想象一下,当客户需要定制一台工业设备时,可能有数百种配置选项相互影响——从基础材质到动力系统,从控制模块到安全装置。如何在SAP系统中优雅地管理这种复杂性?对象相关性(Object Dependencies)就是解决这一挑战的利器。

weixin_42524824的博客 467

Aho Corasick Algorithm

AC自动机,一个内容匹配算法,优于KMP

bigcrab的博客 1750

QtWebApp的使用【在Qt中搭建HTTP服务器】(一)

用Qt和QtWebApp能够实现在C++中开发HTTP Web服务器应用程序。 首先,需要先安装Qt的软件开发工具包。点此下载 其次,下载最新的QtWebApp库。点此下载 下载并解压缩QtWebApp ZIP文件。你将会看到: 如何使用QtWebApp 1)将QtWebApp.zip文件解压到文件夹中,并创建一个名为“ MyFirstWebApp”的新Qt控制台项目。然后,建立如下文件结构: 2)将以下行添加到MyFirstWebApp项目的项目文件中: QT += network include(

饭的笔记本 2万+

C语言经典算法之Aho-Corasick算法(伪代码)

Aho-Corasick算法是一种高效的多模式字符串匹配算法,它构建了一个自动机用于在单次文本扫描过程中查找多个关键词。

weixin_56154577的博客 1476

【007】C++编程必知:原码、补码、反码的全面解读

计算机存储的是数据的补码。原码:计算机中对数字的二进制定点表示方法。比如123的原码是0111 1011。无符号数:原码=反码=补码。有符号数:要分正数和负数,正数的最高位为0,负数的最高位为1。其中,正数的原码、反码、补码都是相同的;负数的反码等于原码的符号数(最高位)不变,其他位取反;补码等于反码+1。比如:-123的原码是1111 1011,反码为1000 0100,补码为1000 0101。原码、补码和反码都是用于计算机表示有符号整数的方法。

Lion_Long的博客 2917

ArduPilot简介

一,什么是ArduPilot? ArduPilot是一个可信的,多用途的,开源的自动驾驶系统。该系统支持了非常多的交通工具类型,包括多旋翼无人机,传统直升机,固定翼飞行器,船,潜艇,巡逻车等。源码由大型开发者社区的专家和爱好者共同开发和维护。也欢迎更多的开发者加入源码的迭代演进,最好的“打开”方式就是加入开发者团队论坛。该论坛对所有人开放,在这里可以深入感受到开发者们对ArduPilot的热爱。 论坛链接:ArduPilot Discourse 开发者指南:Welcome to the ArduPil

从0到1,突破自己 5450

敏感词过滤算法Aho-Corasick

多模式串匹配算法简介 敏感词过滤最基本的原理就是字符串匹配算法,也就是通过维护一个敏感词的字典,当用户输入一段文字内容后,通过字符串匹配算法,来查找用户输入的这段文字,是否包含敏感词。 字符串匹配算法有很多比如BF算法、RK算法、BM算法、KMP算法还有Trie树。前面四种算法都是单模式串匹配算法,只有Trie树是多模式串匹配算法。 我们可以针对每个敏感词,通过单模式匹配算法与用户输入的文字内容进行匹配。但是这样做的话,每个需要匹配的敏感词都需要扫描一遍用户输入的内容。如果敏感词有很多,并且用户输入的内容很

极客神殿 4210

AMBA-CHI协议详解(十)

该规范提供了一个Request Retry(请求重试)机制,确保当请求到达一个Completer 时,它要么被接受,要么被给予一个RetryAck响应,以防止阻塞REQ通道。

Crazzy_M的博客 984

Aho-Corasick算法项目教程

Aho-Corasick算法项目教程 项目介绍 Aho-Corasick算法是一种高效的多模式字符串匹配算法,广泛应用于文本搜索和处理领域。该项目基于Aho-Corasick算法实现了一个Python库,提供了快速且内存有效的多模式字符串搜索功能。通过构建一个自动机,该库能够在文本中同时查找多个关键词,适用于需要快速匹配大量预定义字符串的应用场景。 项目快速启动 安装 首先,确保你已经安装了Pyt...

gitblog_00753的博客 728

基于Simulink的光伏+储能家庭能源管理系统仿真

本文通过Simulink建模,分析了家庭光伏+储能系统的优化调度问题。针对光伏发电与用电高峰不匹配导致电费节省有限的问题,构建了包含5kW光伏、10kWh电池和6kW负荷的完整模型,设计了无控、规则控制和24小时经济优化三种策略。仿真结果显示,经济优化策略可使日电费降低32%,光伏自用率从45%提升至89%,尤其在晚高峰时段能显著减少高价购电。文章详细介绍了物理层建模、分时电价实现和控制策略设计方法,并探讨了天气预测、V2H等高级扩展功能,为家庭能源智能管理提供了实用解决方案。

xiaoheshang_123的博客 188

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

关键字多模式匹配算法Aho-Corasick

Aho-Corasick 算法是一种强大的多模式匹配工具,特别适合需要高效匹配多个关键词的场景。尽管它在空间开销和预处理时间上有一定代价,但其线性的匹配时间复杂度和并发友好的特性使其成为许多实际应用中的首选算法。

Smart、Zhou 1415

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Aho-Corasick算法实现类

刚刚翻Aho-Corasick算法,打算看看具体情况,发现一个有趣的网页,可以提供该算法的可视化,就先占个位置,发个链接(http://blog.ivank.net/aho-corasick-algorithm-in-as3.html),今晚有空再看看。 —————— 终于舍得看AC了……囧。 学习AC算法,首先要理解状态机(有限状态机)的概念,然后学会Trie的实现。接着,就可以更好的理解

BetaBin 5621

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Aho-Corasick算法学习

1、概述Aho-Corasick自动机算法(简称AC自动机)1975年产生于贝尔实验室。该算法应用有限自动机巧妙地将字符比较转化为了状态转移。此算法有两个特点,一个是扫描文本时完全不需要回溯,另一个是时间复杂度为O(n),时间复杂度与关键字的数目和长度无关。好了,我们先看下最原始的多模式匹配算法:主串T,n=strlen(T)。模式串Pi mi = strlen(pi) for

么刚的专栏 3万+

Aho-Corasick 算法

  最近在研究一些字符串匹配算法,也是由于工作上的需要,强力推荐一本书《柔性字符串匹配》,一本很好的书。网上可以随时搜索到。还是说正题吧。我的前几天研究了一下多模式匹配算法,选了Aho-Corasick算法,因为这个比较基础,相比其他多模式匹配算法其要容易理解的多。所以,现在简单总结一下书上的内容,加深自己的理解。   首先了解一下多模式匹配,就是同时搜索多个模式串。其实都是基于单模式...

abd456654的博客 345

【亲测免费】 Aho-Corasick算法的高效Golang实现

Aho-Corasick算法的高效Golang实现 项目基础介绍和主要编程语言 该项目是一个基于Golang的高效Aho-Corasick算法实现,名为ahocorasick。Aho-Corasick算法是一种用于多模式字符串匹配的高效算法,特别适用于需要在大文本中快速查找多个关键词的场景。该项目通过使用双数组Trie(Double Array Trie)替代传统的链表Trie,显著提升了算法的性...

gitblog_00009的博客 432

**深入探索Aho-Corasick算法的高效实现 —— aho-corasick-lua项目介绍**

深入探索Aho-Corasick算法的高效实现 —— aho-corasick-lua项目介绍 一、项目概述 在文本处理和模式匹配领域中,aho-corasick-lua无疑是一颗璀璨的明星。这个项目提供了C++与Lua版本的Aho-Corasick(AC)字符串匹配算法实现,旨在为开发者提供高性能的文本搜索解决方案。起初从纯Lua实现起步,在遇到性能瓶颈后,团队转向了更为高效的C/C++实现方式...

gitblog_00029的博客 437

高效字符串搜索利器:Aho-Corasick算法在PHP中的实现

高效字符串搜索利器:Aho-Corasick算法在PHP中的实现 项目介绍 Aho Corasick in PHP 是一个轻量级的PHP库,实现了著名的Aho-Corasick字符串搜索算法。该算法由Alfred V. Aho和Margaret J. Corasick于1975年提出,能够在文本中高效地同时搜索多个关键词。 这个库完全由纯PHP编写,代码自包含在一个文件 ahocorasick.p...

gitblog_01080的博客 1199

基于Aho-Corasick算法的Ahocorasick库的使用

由于最近项目中需要使用Python的库进行模式匹配,因此记录该库所使用的到的算法(AC算法)的概要以及该库在Python中的具体使用方法。算法是多模式匹配中的经典算法,目前在实际应用中较多。算法对应的数据结构是自动机,简称AC自动机Automaton。该算法能够识别出一个给定的语句中包含了哪些词典库中特定的词语,具有很不错的模式匹配作用。

qq_52965253的博客 2911
上一篇: java实现简单的缓存机制
下一篇: Mahout文本聚类实例
hellocdw
博客等级 码龄15年 5粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值