当前位置: 首页 > news >正文

字符串算法之AC 自动机(Aho-Corasick Algorithm, 多模式匹配)详细解读

AC自动机(Aho-Corasick Algorithm)是一种高效的多模式字符串匹配算法,用于同时查找多个模式串(子串)在文本串中的出现位置。它结合了字典树(Trie)和有限状态机(Finite State Machine)的思想,能够在 O(n+m+z)的时间复杂度内完成匹配,其中 n 是文本的长度,m 是所有模式串的总长度,z 是匹配结果的数量。

AC自动机的基本原理

AC自动机主要通过以下几个步骤实现:

  1. 构建字典树(Trie)

    • 将所有的模式串插入到一个字典树中。字典树的每个节点代表一个字符的状态,路径上的字符代表一个模式串。
  2. 构建失败指针

    • 对字典树进行扩展,建立每个节点的失败指针。这些失败指针用于在匹配过程中提供回溯的能力,当当前字符不匹配时,利用失败指针转移到其他状态。
  3. 进行模式匹配

    • 在输入文本上进行扫描,根据字典树和失败指针进行状态转移,并记录匹配结果。

详细步骤

1. 构建字典树
  • 将所有模式串插入到字典树中,构建出一个Trie树。每个节点存储该字符和指向子节点的指针。
2. 构建失败指针
  • 通过BFS(广度优先搜索)遍历字典树,为每个节点计算失败指针。失败指针指向当前节点失配时应转移到的节点。

  • 失败指针的构建规则:

    • 如果当前节点的某个字符与文本串不匹配,则沿着失败指针找到最长的可匹配前缀节点。
3. 进行模式匹配
  • 从文本的第一个字符开始,遍历文本。
  • 根据当前字符的状态,进行状态转移。若匹配成功,继续查找下一个字符;若匹配失败,则沿着失败指针进行转移。
  • 若到达某个节点时标记为模式串的结束,记录该模式串的出现位置。

AC自动机的Java实现

以下是AC自动机的Java实现示例:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;class AhoCorasick {private class TrieNode {Map<Character, TrieNode> children = new HashMap<>();TrieNode fail; // 失败指针List<String> outputs = new ArrayList<>(); // 输出的模式串public TrieNode() {this.fail = null;}}private TrieNode root;public AhoCorasick() {root = new TrieNode();}// 插入模式串public void insert(String pattern) {TrieNode currentNode = root;for (char c : pattern.toCharArray()) {currentNode = currentNode.children.computeIfAbsent(c, k -> new TrieNode());}currentNode.outputs.add(pattern); // 将模式串存储到输出列表}// 构建失败指针public void buildFailPointers() {List<TrieNode> queue = new ArrayList<>();root.fail = root;for (TrieNode child : root.children.values()) {child.fail = root; // 根节点的失败指针指向自己queue.add(child);}while (!queue.isEmpty()) {TrieNode currentNode = queue.remove(0);for (Map.Entry<Character, TrieNode> entry : currentNode.children.entrySet()) {char c = entry.getKey();TrieNode child = entry.getValue();queue.add(child);// 查找当前节点的失败指针TrieNode failNode = currentNode.fail;while (failNode != root && !failNode.children.containsKey(c)) {failNode = failNode.fail;}child.fail = failNode.children.getOrDefault(c, root); // 失败指针child.outputs.addAll(child.fail.outputs); // 继承失败指针的输出}}}// 进行模式匹配public List<int[]> search(String text) {List<int[]> results = new ArrayList<>();TrieNode currentNode = root;for (int i = 0; i < text.length(); i++) {char c = text.charAt(i);while (currentNode != root && !currentNode.children.containsKey(c)) {currentNode = currentNode.fail; // 没有匹配,使用失败指针}currentNode = currentNode.children.getOrDefault(c, root); // 继续匹配// 如果有输出,说明找到了模式串for (String pattern : currentNode.outputs) {results.add(new int[] { i - pattern.length() + 1, pattern.length() });}}return results;}public static void main(String[] args) {AhoCorasick ac = new AhoCorasick();String[] patterns = {"he", "she", "his", "hers"};for (String pattern : patterns) {ac.insert(pattern);}ac.buildFailPointers();String text = "ushers";List<int[]> matches = ac.search(text);for (int[] match : matches) {System.out.println("Pattern found at index: " + match[0] + ", length: " + match[1]);}}
}

代码解读

  1. TrieNode类

    • TrieNode表示字典树的节点,包含子节点的映射、失败指针和输出模式串列表。
  2. 插入模式串

    • insert方法接受一个模式串,并将其插入到字典树中。每次插入都更新当前节点,并将模式串存储到输出列表中。
  3. 构建失败指针

    • buildFailPointers方法通过BFS构建失败指针,确保每个节点都有合适的失败指针,并将输出模式串从失败节点继承到当前节点。
  4. 进行模式匹配

    • search方法扫描输入文本并根据字典树和失败指针进行状态转移,记录匹配的模式串及其位置。
  5. 主函数

    • 在主函数中,创建AC自动机实例,插入多个模式串,构建失败指针,然后在文本中查找匹配并打印结果。

AC自动机的优缺点

优点
  • 高效性:AC自动机在处理多个模式串时非常高效,适合需要同时查找多个模式串的场景。
  • 线性时间复杂度:匹配过程的时间复杂度为 O(n+m+z),其中 z 是匹配结果的数量。
缺点
  • 空间复杂度:由于需要存储字典树和失败指针,空间复杂度相对较高,尤其是模式串数量较多时。
  • 实现复杂性:相比于其他字符串匹配算法(如KMP),AC自动机的实现相对复杂,涉及到字典树的构建和失败指针的维护。

应用场景

AC自动机广泛应用于文本处理、网络监控、数据包过滤、信息检索等领域。它能够高效地处理大规模文本数据,快速匹配多个模式串,尤其适合处理多关键词搜索和匹配的场景。

相关文章:

字符串算法之AC 自动机(Aho-Corasick Algorithm, 多模式匹配)详细解读

AC自动机&#xff08;Aho-Corasick Algorithm&#xff09;是一种高效的多模式字符串匹配算法&#xff0c;用于同时查找多个模式串&#xff08;子串&#xff09;在文本串中的出现位置。它结合了字典树&#xff08;Trie&#xff09;和有限状态机&#xff08;Finite State Machine…...

YoloV10改进:Block改进|使用ContextAggregation模块改善C2f模块|即插即用

摘要 在计算机视觉领域&#xff0c;目标检测与实例分割任务一直是研究的热点。YoloV10作为目标检测领域的佼佼者&#xff0c;凭借其出色的性能和效率赢得了广泛的认可。然而&#xff0c;随着技术的不断进步&#xff0c;如何进一步提升YoloV10的性能成为了我们追求的目标。近期…...

学习之高阶编程str方法

__str__方法 问题思考:交互环境下print打印的内容和和直接输入变量&#xff0c;返回的内容不一样这是为什么?. 使用print打印的时候触发的是_str_方法&#xff0c; 注意点: 重写str&#xff0c;必须要记得写return. return返回的必须是一个字符串对象。 class MyClass:def _…...

FreeRTOS:事件标志组

目录 一、简介 二、 事件控制块 三、相关API 四、 应用场景 一、简介 在FreeRTOS中&#xff0c;使用信号量可以实现同步&#xff0c;但是使用信号量来同步的话任务只能与单个的任务进行同步。有时候某个任务可能会需要与多个任务进行同步&#xff0c;此时信号量就无能为力。…...

【高分论文密码】AI赋能大尺度空间模拟与不确定性分析及数字制图

随着AI大语言模型的广泛应用&#xff0c;大尺度空间模拟预测与数字制图技术在不确定性分析中的重要性日益凸显。这些技术已经成为撰写高分SCI论文的关键工具&#xff0c;被誉为“高分论文密码”。大尺度模拟技术能够从不同的时空尺度揭示农业生态环境领域的内在机理和时空变化规…...

智能摆件(墨水屏)

因为需要申请8k的堆&#xff0c;所以需要更改堆的大小 stm32修改堆栈大小&#xff08;堆栈空间不足导致死机&#xff09;_minimum heap size-CSDN博客...

ansible————playbook

一、playbook和ad hoc命令 ad hoc命令是单行&#xff0c;一个简单的任务&#xff0c;运行一次。ansible真正强大的地方是使用ansible的playbook重复运行多次复杂的任务。 一个play是是一组有序的任务&#xff0c;该paly对应着在inventory被选择的主机。一个playbook是一个包含…...

linux日志分割工具logorate快速验证配置是否有效

创建一些文件, 并修改文件的mtime(修改时间) # /var/log/test/*.log touch -d "2024-10-14" test1.log touch -d "2024-10-15" test2.log touch -d "2024-10-16" test3.log touch -d "2024-10-17" test4.log#快速创建一个1G的大文…...

Unity3D URP画面品质的上限如何详解

Unity3D是一款广泛应用于游戏开发的引擎&#xff0c;它提供了多种渲染管线用于实现不同的画面品质。其中一种渲染管线是Universal Render Pipeline&#xff08;简称URP&#xff09;&#xff0c;它是Unity3D的一种轻量级渲染管线&#xff0c;专注于提供高性能和可移植性。 对惹…...

风管阻力计算

风管阻力主要包括摩擦阻力和局部阻力两大类。摩擦阻力:空气在风管内流动时,与管壁的摩擦作用导致的能量损失,与管道长度、断面尺寸、风速、空气密度等参数有关。局部阻力:风管系统中的弯头、三通、变径、阀门等部件,由于改变了气流的流动方向或速度,导致的额外能量损失,用局部阻…...

【redis】redis的多线程和IO多路复用

【redis】redis的多线程和IO多路复用 【一】前言【二】Redis单线程和多线程问题的背景【1】Redis的单线程【2】Redis为什么选择单线程&#xff1f;【3】Redis为什么开始利用多核&#xff1f;【4】Redis当前的性能瓶颈【5】Redis的主线程如何和IO线程协同 【三】IO多路复用的理解…...

webstorm 编辑器配置及配置迁移

1.下载地址 WebStorm&#xff1a;JetBrains 出品的 JavaScript 和 TypeScript IDE 其他版本下载地址 2.安装 点击下一步安装&#xff0c;可根据需要是否删除已有版本 注意&#xff1a; 完成安装后需要激活 3.设置快捷键 以下为个人常用可跳过或根据需要设置 如&#xff1a…...

Oracle19.25发布,如何打补丁到19.25

一. 19.25发布 2024年10月16日 19c 19.25补丁发布 文档编号19202410.9&#xff0c;文档编码规则&#xff1a; 19&#xff08;版本号&#xff09;2024&#xff08;年份&#xff09;07&#xff08;当季的第一个月01/04/07/10&#xff09;.9 一般每个季度的首月中15号左右发布…...

vue3中,拦截双击事件的第一次点击,写一些逻辑

在 Vue 3 中&#xff0c;如果想要拦截双击事件的第一次点击并执行一些逻辑&#xff0c;你可以使用一个状态变量来跟踪第一次点击事件&#xff0c;并在第二次点击时阻止第一次点击逻辑的执行。以下是一个实现示例&#xff1a; <template><divmousedown"handleMou…...

落地 ZeroETL 轻量化架构,ByteHouse 推出“四个一体化”策略

在数字化转型的浪潮中&#xff0c;数据仓库作为企业的核心数据资产&#xff0c;其重要性日益凸显。随着业务范围扩大&#xff0c;企业也会使用不同的数据仓库来管理、维护相关数据。研发人员需要花费大量时间和精力&#xff0c;从中导出数据&#xff0c;然后进行手动整理、转换…...

如何提高LabVIEW编程效率

提高LabVIEW编程效率对开发者来说非常重要&#xff0c;尤其是在处理复杂项目或紧迫的开发周期时。以下是一些可以显著提升LabVIEW编程效率的技巧&#xff0c;从代码结构、工具使用到团队协作的多个角度进行详细分析&#xff1a; 1. 模块化设计 模块化设计 是提高代码可维护性和…...

Android 开发 TabLayout 自定义指示器长度

前言 原生 TabLayout 的指示器长度是充满整个屏幕的&#xff0c;但在实际开发中 UI 会设计成 指示器的长度等于或者小于标题字体长度&#xff0c;如图 如果设置成跟字体长度一样即使用 API: mTabLayout.setTabIndicatorFullWidth(false);或者在 xml 布局文件中的TabLayout标签…...

构造mex(牛客周赛 Round 59)

题目链接&#xff1b; D-构造mex_牛客周赛 Round 59 (nowcoder.com) 题目描述&#xff1a; 输出和输出描述&#xff1a; 输入样例&#xff1a; 3 6 3 3 7 4 3 6 6 0 输出样例&#xff1a; NO YES 4 0 1 2 YES 1 1 1 1 1 1 分析&#xff1a; 数学思维题&#xff0c;赛后看了一…...

RabbitMQ 交换机的类型

在 RabbitMQ 中&#xff0c;交换机&#xff08;Exchange&#xff09;是一个核心组件&#xff0c;负责接收来自生产者的消息&#xff0c;并根据特定的路由规则将消息分发到相应的队列。交换机的存在改变了消息发送的模式&#xff0c;使得消息的路由更加灵活和高效。 交换机的类…...

机器人顶会参会经验——许华哲老师PRE-IROS 2024分享

摘要&#xff1a;清华大学交叉信息学院许华哲老师在PRE-IROS 2024上分享了机器人顶会参会技巧&#xff0c;包括社交和活动选择方面的实用建议等内容。本文整理了许老师在直播中分享的干货。 在刚刚过去的PRE-IROS 2024论文预分享会上&#xff0c;清华叉院许华哲老师全方位解析…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

PostgreSQL——环境搭建

一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在&#xff0…...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...