【算法】AC自动机的优化:增量更新与删除

一、概述

AC自动机(Aho-Corasick Automation)是著名的多模匹配算法,源于贝尔实验室,并且在实际应用中得到广泛的引用,且具有以下特点:

  • 只需要扫描一次文本,即可获取所有匹配该文本的模式串
  • 复杂度O(n)
  • 以树的结构进行存储
  • 通过Fail节点和Fail指针来提高匹配效率

对于AC自动机的具体实现,感兴趣可以自行搜索。

但是在实际应用场景中,AC自动机不仅仅只考虑匹配模式,还要考虑其模式串数据源的处理,比如模式串数据源的频繁变动(更新or移除数据),针对这样的情况下如果不断地对AC检测树进行推倒重建,在性能上消耗是十分庞大的。

因此,基于这样的场景,我们需要支持动态、快速、便捷地对已生成的AC检测树进行数据的插入、删除。

二、原理

原理很好理解,即:

  1. 新增节点自前往后遍历,删除节点自后往前遍历,逐一获取需要新增/删除的节点
  2. 更新指向该节点的Fail指针
  3. 更新该节点指向的Fail节点
  4. 在AC检测树中合并/移除该节点

在第2步中,原来的AC检测树的节点是不记录相关信息的,因此需要引入一个列表来管理该信息。

1. 新增节点

新增节点,即需要将新增加需要匹配的模式串源数据合并到已构建好的AC检测树中。

假定新增模式串为Z,已构建的AC检测树为AC_TREE

  • 判断ZAC_TREE的中最长前缀,并记录最长前缀的最后一个节点NODE
  • NODE作为遍历起点并开始遍历Z
    • 为新字符NEW_CHAR创建节点NEW_NODE并添加到NODE
    • 沿着NODE的Fail指针向上查找,直至找到某个节点下的子节点是NEW_CHAR,记录该节点的子节点为NEW_FAIL_NODE(如果没找到,则NEW_FAIL_NODE = ROOT
    • 更新NEW_NODE的Fail节点为NEW_FAIL_NODE
    • 获取Fail节点为NODE的节点列表REVER_NODE_LIST,并遍历
      • 判断REVER_NODE_LIST中节点的子节点REVER_CHILD_NODE的值是否有NEW_CHAR,如果有,则将REVER_CHILD_NODE的Fail节点设置为NEW_NODE,并更新NEW_NODEREVER_NODE_LIST
    • 设置NEW_NODE的其他属性

图文说明:

【初始状态】
在这里插入图片描述
【新增模式串后:ers】
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 删除节点

删除节点,即需要将某些模式串源数据已构建好的AC检测树中移除。

假定移除的模式串为Z,已构建的AC检测树为AC_TREE

  • 判断ZAC_TREE的位置,找到Z最后一个字符在AC_TREE中的节点NODE(如果不存在该模式串则跳出处理流程)
  • NODE作为遍历起点并开始反向遍历Z
    • 判断NODE是否存在其他子节点,有则跳出循环
    • 获取Fail节点为NODE的节点列表REVER_NODE_LIST,并遍历
      • REVER_NODE_LIST中的节点REVER_NODE的Fail节点设置为NODE的Fail节点
      • 更新NODEREVER_NODE_LIST
    • 更新NODE的Fail节点为NULL
    • 删除NODE,并更新NODE的父节点PARENT_NODE的子节点列表

图文说明:

【初始状态】
在这里插入图片描述

【删除模式串后:ers】
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、实现流程

P.S. 通过伪代码形式给出主要代码流程

// 新增节点
AddNode(list[str_1..str_n])for i ← 0 to n-1 dostr ←  list[i]; pos ← 0; node ← rootfor j ← pos to str.len() dopos ← jnode ← node.childNodeList[str[pos]]now_node ← node for j ← pos to str.len() dochr ← str[j]// 查找Fail节点fail_node ← GetFailNode(now_node, chr)// 创建新节点next_node  ← CreateNewNode(now_node, chr) next_node, fail_node ← SetFailNode(next_node, fail_node)// 处理需要指向该节点的Fail指针for k ← 0 to now_node.reverseFailNodeList dotmp_node ← now_node.reverseFailNodeList[k][chr]tmp_node , next_node ← SetFailNode(tmp_node , next_node)now_node. reverseFailNodeList[k].childNodeList[chr] ← tmp_node // 删除节点
DelNode(list[str_1..str_n])for i ← 0 to n-1 dostr ←  list[i]; pos ← 0; node ← root; nodeList  ← []for j ← pos to str.len() dopos ← jnodeList.add(node)node ← node.childNodeList[str[pos]]nodeList.reverse()for j ← pos to str.len() donow_node ← nodeList[j]fail_node ← now_node.faliNode// 处理指向该节点的所有Fail指针for k ← 0 to now_node.reverseFailNodeList dotmp_node ← now_node.reverseFailNodeList[k][chr]tmp_node , next_node ← SetFailNode(tmp_node , next_node)now_node. reverseFailNodeList[k].childNodeList[chr] ← tmp_node// 处理当前节点的Fail节点now_node, tmpFail_node← SetFailNode(now_node, NULL) // 删除该节点delete now_node.parentNode.childNodeList[now_node.char]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/748248.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS扩展选择器

文章目录 1. 并集选择器2. 交集选择器3. 后代选择器4. 子代选择器5. 兄弟选择器5.1. 相邻兄弟选择器5.2. 通用兄弟选择器 6. 属性选择器7. 伪类选择器7.1. 动态伪类7.2. 结构伪类7.3. 否定伪类 8. 伪元素选择器9. Google 改进案例 1. 并集选择器 选中多个选择器对应的元素。一…

如何在Linux上使用git远程上传至gitee托管(add-commit-push指令详解)

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …

力扣209. 长度最小的子数组

思路:题目是 数组和 > target,不是等于target 双指针法:用for循环中的 r 来界定右边界的下标,右边界每移动一位,左边界可能需要移动多位,所以内部再用while, 当满足 数组和>target时,记录…

C语言基础之结构体

文章目录 一、结构体1、结构体概述2、结构体类型的定义方式(1)先定义结构体类型,再定义结构体变量(2)结构体类型、变量同时定义(3)一次性结构体 3、结构体成员的初始化(1)结构体初始化(2)清空结…

RISC-V Optimization Guide(笔记)

官网发表的文章地址:RISC-V Optimization Guide B站有人做过解读视频,这篇文章也是看视频时做的笔记:视频地址 一、标量整数优化 1.1 常量的具体化 使用lui/addiw将立即数加载至寄存器,当立即数低12位的最高位为1时&#xff0c…

数据库 | MYSQL这个复杂系统如何上手?

当你不知道从何入手研究或解决一个复杂系统的问题时,通常意味着你没有找到合适的切入点或者缺乏对系统整体和细节之间联系的理解。在这种情况下,一个有用的策略是寻找系统的基本原理或构成要素。 小时候,你可能也玩过玩具四驱车。有的四驱车…

从零开始利用MATLAB进行FPGA设计(三)将Simulink模型转化为定点数据类型

文章灵感来源于MATLAB官方免费教程:HDL Coder Self-Guided Tutorial 考虑到MATLAB官网的英文看着慢,再加上视频讲解老印浓浓的咖喱味,我决定记录利用MATLAB&Simulink&SystemGenerator进行FPGA数字信号处理的学习过程。 往期回顾&am…

什么是响应式设计?响应式设计的基本原理是什么?如何做?

文章目录 一、是什么二、实现方式媒体查询百分比vw/vhrem小结 三、总结参考文献 一、是什么 响应式网站设计(Responsive Web design)是一种网络页面设计布局,页面的设计与开发应当根据用户行为以及设备环境(系统平台、屏幕尺寸、屏幕定向等)…

软考高级:BPR 和 BPM概念和例题

作者:明明如月学长, CSDN 博客专家,大厂高级 Java 工程师,《性能优化方法论》作者、《解锁大厂思维:剖析《阿里巴巴Java开发手册》》、《再学经典:《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

【四 (1)数据可视化之如何选用正确的图表】

目录 文章导航一、数据分析中可视化的作用1、揭示数据关联和模式2、支持数据分析和决策3、提升沟通和共享效果4、强调关键信息和发现5、增强故事叙述和记忆效果6、有效增强数据交互性数据7、复杂信息易理解8、数据多维度显示 二、如何选用合适的图表1、简洁性避免使用过于复杂或…

软考高级:企业应用集成概念和例题

作者:明明如月学长, CSDN 博客专家,大厂高级 Java 工程师,《性能优化方法论》作者、《解锁大厂思维:剖析《阿里巴巴Java开发手册》》、《再学经典:《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

八 超级数据查看器   讲解稿   详情3  分享和外观

八 超级数据查看器 讲解稿 详情3 分享和外观 app下载地址 下载地址4 ​ 讲解稿全文: 第3讲 分享 顶栏颜色 外观设置 现在讲解分享功能。点击,会打开分享对话框,我们这里演示2个,可以按照标题做出分享,在第一组…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Badge)

可以附加在单个组件上用于信息标记的容器组件。 说明: 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 子组件 支持单个子组件。 说明: 子组件类型:系统组件和自定义组件&#xf…

异次元发卡源码系统/荔枝发卡V3.0二次元风格发卡网全开源源码

– 支付系统,已经接入易支付及Z支付免签接口。 – 云更新,如果系统升级新版本,你无需进行繁琐操作,只需要在你的店铺后台就可以无缝完成升级。 – 商品销售,支持商品配图、会员价、游客价、邮件通知、卡密预选&#…

腾讯在线文档下载文档html格式

腾讯在线文档下载文档html格式 步骤 chrome 浏览器打开该文档(edge不行) 同时按住ctrlp快捷键调出腾讯文档内置的打印页面,打印范围要选择整个工作薄,纸张建议调大一点,边距建议较窄,缩放要选择宽度撑满&…

“风口”上的量化大厂“绣球”抛向中低频人才

量化人才这几年是人才舞台上的“香饽饽”。 遵循着低频不如高频、小厂不如大厂的薪资逻辑,各路人才被各路机构“哄抢”,薪资一路走高。 但2024年的“信号”再强烈不过——量化大厂们到了改变的时候了。 而量化大厂们显然对此已“心知肚明”....... “…

空气源热泵、地源热泵和水源热泵三种热泵的优缺点和选型比较

空气源热泵 空气源热泵是由电动机驱动的,利用空气中的热量作为低温热源,经过空调冷凝器或蒸发器进行热交换,然后通过循环系统,提取或释放热能,利用机组循环系统将能量转移到建筑物内用户需求。 1、适用范围广:适用温度范围在-7至40℃,并且一年四季全天候使用,不受阴、…

软件测试 —— 案例系统缺陷报告

知识: 1、缺陷等级: 1-Urgent(致命错误):影响全局的死机、通信中断、重要业务不能完成 2-Very High(严重错误):规定的功能没有实现或不完整或产生错误结果;使系统不稳定、或破坏数据等 3-High(一般错误):…

Github 2024-03-16 Rust开源项目日报 Top10

根据Github Trendings的统计,今日(2024-03-16统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10TypeScript项目2Go项目1RustDesk: 用Rust编写的开源远程桌面软件 创建周期:1218 天开发语言:Rust, Dart协议类型:GNU Affero Gene…

NCDA大赛中哪些HTML5设计作品展现出色?

与传统的HTML网页设计相比,HTML5网页设计主要是对网页内容的加强。HTML5已成为目前最流行的标记语言,拥有成熟的社区和广泛的浏览器支持,HTML5完整的功能和强大的扩展性使设计师和开发者能够点铁成金。HTML5可以一手控制更多可控元素&#xf…