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

字符串匹配算法:暴力匹配、KMP 算法、Boyer-Moore 算法、Rabin-Karp 算法

字符串匹配算法

字符串匹配算法是在一个字符串(称为文本)中查找另一个字符串(称为模式)出现的位置或者是否存在的算法。常见的字符串匹配算法包括暴力匹配、KMP算法、Boyer-Moore算法和Rabin-Karp算法。下面是对这些算法的简要介绍:

暴力匹配(Brute Force)算法:

  • 算法原理:暴力匹配算法是最简单的一种字符串匹配算法。它的原理是从文本的每一个可能的位置开始,依次比较文本中的子串与模式串是否匹配。如果匹配成功,则返回匹配的位置;否则,继续尝试下一个位置。
  • 时间复杂度:平均情况下为O(m*n),其中m为文本长度,n为模式长度。
  • 优点:
    • 算法简单易懂,容易实现。
    • 不需要额外的预处理步骤。
  • 缺点:
    • 效率较低,时间复杂度为O(m*n),其中m为文本长度,n为模式长度。
    • 对于大规模文本和模式,性能较差。

代码示例:

/*** 暴力匹配算法** @param text 目标文本* @param pattern 匹配模式* @returns 返回匹配模式在目标文本中的起始位置,如果没有找到匹配则返回-1*/
function bruteForce(text, pattern) {const m = text.length;const n = pattern.length;// 遍历文本串,查找模式串for (let i = 0; i <= m - n; i++) {let j = 0;// 逐个比较文本串和模式串的字符while (j < n && text[i + j] === pattern[j]) {j++;}// 如果模式串全部匹配成功if (j === n) {return i; // 返回匹配的起始位置}}// 没有找到匹配return -1; // 没有找到匹配
}// 示例用法
const text = "hello world";
const pattern = "world";
console.log(bruteForce(text, pattern)); // 输出: 6

KMP(Knuth-Morris-Pratt)算法:

  • 算法原理:KMP算法通过预处理模式串构建部分匹配表(也称为next数组),然后在匹配过程中根据部分匹配表来移动模式串,避免重复比较已经匹配的部分。
  • 时间复杂度:O(m+n),其中m为文本长度,n为模式长度。
  • 优点:
    • 在大多数情况下,时间复杂度为O(m+n),具有较高的效率。
    • 通过部分匹配表避免了不必要的比较,提高了搜索速度。
  • 缺点:
    • 实现较为复杂,需要构建部分匹配表。
    • 在特定情况下,性能可能不如其他算法。

代码示例:

/*** 生成KMP算法中的部分匹配表** @param pattern 待匹配的字符串* @returns 返回部分匹配表*/
function kmpTable(pattern) {// 获取模式串的长度const n = pattern.length;// 初始化表数组,初始值都为0const table = new Array(n).fill(0);// 初始化指针i和jlet i = 1, j = 0;// 当i小于n时,循环执行以下操作while (i < n) {// 如果模式串的第i个字符与第j个字符相等if (pattern[i] === pattern[j]) {// j指针向后移动一位j++;// 将j的值赋给表数组的第i个位置table[i] = j;// i指针向后移动一位i++;// 如果j大于0} else if (j > 0) {// 将j的值更新为表数组的第j-1个位置的值j = table[j - 1];// 如果j等于0} else {// i指针向后移动一位i++;}}// 返回表数组return table;
}/*** 使用KMP算法在文本中搜索模式串** @param text 文本* @param pattern 模式串* @returns 返回模式串在文本中的起始位置,如果未找到则返回-1*/
function kmpSearch(text, pattern) {const m = text.length;const n = pattern.length;if (n === 0) {return 0;}// 生成部分匹配表const table = kmpTable(pattern);let i = 0, j = 0;while (i < m) {// 如果当前字符匹配成功if (text[i] === pattern[j]) {i++;j++;// 如果已经匹配完整个模式串if (j === n) {return i - n; // 返回匹配的起始位置}// 如果当前字符匹配失败,且模式串的下一个字符不是第一个字符} else if (j > 0) {// 根据部分匹配表进行跳转j = table[j - 1];// 如果当前字符匹配失败,且模式串的下一个字符是第一个字符} else {i++;}}// 没有找到匹配return -1; // 没有找到匹配
}// 示例用法
const text = "hello world";
const pattern = "world";
console.log(kmpSearch(text, pattern)); // 输出: 6

Boyer-Moore算法:

  • 算法原理:Boyer-Moore算法是一种启发式的字符串匹配算法,它利用了模式串中的信息来尽可能地跳过不必要的比较。主要有两种启发式规则:坏字符规则和好后缀规则。
  • 时间复杂度:最坏情况下为O(m*n),但平均情况下具有较高的效率。
  • 优点:
    • 在实际应用中通常具有较高的效率,尤其是在模式串较长、字符集较大的情况下。
    • 利用了启发式规则,能够快速跳过不匹配的位置,减少比较次数。
  • 缺点:
    • 实现相对复杂,需要理解和实现坏字符规则和好后缀规则。
    • 在某些情况下,性能可能不如其他算法。

代码示例:

/*** Boyer-Moore 字符串匹配算法** @param text 待匹配的文本* @param pattern 待匹配的模式* @returns 返回匹配到的起始位置,若未找到则返回-1*/
function boyerMoore(text, pattern) {const m = text.length;const n = pattern.length;if (n === 0) {return 0;}// 构建字符最后出现位置的映射const skip = {};for (let i = 0; i < n - 1; i++) {skip[pattern[i]] = n - i - 1;}skip[pattern[n - 1]] = n;let i = 0;while (i <= m - n) {let j = n - 1;// 从后往前匹配文本和模式while (j >= 0 && text[i + j] === pattern[j]) {j--;}if (j === -1) {return i; // 如果全部匹配成功,返回匹配的起始位置}// 根据字符最后出现位置的映射计算下一个匹配位置i += skip[text[i + n - 1]] || n;}return -1; // 没有找到匹配
}// 示例用法
const text = "hello world";
const pattern = "world";
console.log(boyerMoore(text, pattern)); // 输出: 6

Rabin-Karp算法:

  • 算法原理:Rabin-Karp算法利用哈希函数来对模式串和文本中的子串进行哈希计算,然后比较哈希值来确定是否匹配。它适用于在一段文本中搜索多个不同的模式串。
  • 时间复杂度:平均情况下为O(m+n),其中m为文本长度,n为模式长度。
  • 优点:
    • 在多个模式串匹配和字符串搜索中具有良好的性能。
    • 利用哈希函数实现了快速的模式匹配。
  • 缺点:
    • 对于哈希冲突的处理和哈希函数的设计需要注意,影响算法的准确性和性能。
    • 在某些情况下,哈希函数的计算可能会造成额外的开销。

代码示例:

/*** Rabin-Karp 字符串匹配算法** @param text 文本字符串* @param pattern 模式字符串* @returns 返回模式字符串在文本字符串中首次出现的位置,若未找到则返回 -1*/
function rabinKarp(text, pattern) {const m = text.length;const n = pattern.length;if (n === 0) {return 0;}// 字符集大小const d = 256; // 字符集大小// 一个质数const q = 101; // 一个质数let p = 0, t = 0, h = 1;// 计算哈希值的基础值for (let i = 0; i < n - 1; i++) {h = (h * d) % q;}// 计算模式串和文本串的哈希值for (let i = 0; i < n; i++) {p = (d * p + pattern.charCodeAt(i)) % q;t = (d * t + text.charCodeAt(i)) % q;}// 遍历文本串,查找匹配for (let i = 0; i <= m - n; i++) {// 哈希值相等且字符串相等时,返回匹配的起始位置if (p === t && text.substring(i, i + n) === pattern) {return i; // 返回匹配的起始位置}// 更新文本串的哈希值if (i < m - n) {t = (d * (t - text.charCodeAt(i) * h) + text.charCodeAt(i + n)) % q;if (t < 0) {t += q;}}}// 没有找到匹配return -1; // 没有找到匹配
}// 示例用法
const text = "hello world";
const pattern = "world";
console.log(rabinKarp(text, pattern)); // 输出: 6

相关文章:

字符串匹配算法:暴力匹配、KMP 算法、Boyer-Moore 算法、Rabin-Karp 算法

字符串匹配算法 字符串匹配算法是在一个字符串&#xff08;称为文本&#xff09;中查找另一个字符串&#xff08;称为模式&#xff09;出现的位置或者是否存在的算法。常见的字符串匹配算法包括暴力匹配、KMP算法、Boyer-Moore算法和Rabin-Karp算法。下面是对这些算法的简要介…...

微信小程序接入百度地图(微信小程序插件)使用文档

第一步配置域名 :在微信公众平台登录后配置服务域名称:https://apis.map.qq.com 第二步申请密钥 申请开发者密钥申请地址 第三步使用插件 选择添加插件 搜索腾讯位置服务地图选点 选择要授权的小程序 授权完毕会在这里显示插件信息 第四步查看使用文档 跳转至文…...

如果需要在Log4j中记录特定的异常信息,应该如何实现?如何动态地更改Log4j的日志级别?

如果需要在Log4j中记录特定的异常信息&#xff0c;应该如何实现&#xff1f; 在Log4j中记录特定的异常信息&#xff0c;你可以使用Logger类的error、warn、info等方法&#xff0c;这些方法通常接受一个字符串消息和一个Throwable对象&#xff08;如异常&#xff09;作为参数。下…...

Rust入门:C++和Rust动态库(dll)的相互调用

无论是C调用Rust动态库还是Rust调用C动态库&#xff0c;其操作基本都是一样地简单&#xff0c;基本和C调用C的动态库没什么区别&#xff0c;只需要列出所需要导入的函数&#xff0c;并链接到相应的lib文件即可。 这里&#xff0c;在windows中&#xff0c;我们以dll动态库为例说…...

第三篇【传奇开心果系列】Python的自动化办公库技术点案例示例:深度解读Pandas股票市场数据分析

传奇开心果博文系列 系列博文目录Python的自动化办公库技术点案例示例系列 博文目录前言一、Pandas进行股票市场数据分析常见步骤和示例代码1. 加载数据2. 数据清洗和准备3. 分析股票价格和交易量4. 财务数据分析 二、扩展思路介绍1. 技术指标分析2. 波动性分析3. 相关性分析4.…...

3.11笔记2

目前使用的格里高利历闰年的规则如下&#xff1a; 公元年分非4的倍数&#xff0c;为平年。公元年分为4的倍数但非100的倍数&#xff0c;为闰年。公元年分为100的倍数但非400的倍数&#xff0c;为平年。公元年分为400的倍数为闰年。 请用一个表达式 (不能添加括号) 判断某一年…...

web服务器基础

目录 web服务器简介 (1)什么是www (2)网址及HTTP简介 (3)http协议请求的工作流程 主配置文件内的参数 目录标签 缺点 虚拟主机vhosts 示例的格式如下 实例 多IP实现多网页 修改监听端口号 hosts文件及域名解析 修改hosts文件内缓存格式 实现效果 实现多域名解析IP地址 在linux…...

矢量图片转换软件Vector Magic mac中文版功能特色

Vector Magic mac中文版是一款非常流行的矢量图片转换软件&#xff0c;它的功能特色主要体现在以下几个方面&#xff1a; 首先&#xff0c;Vector Magic mac中文版拥有出色的矢量转换能力。它采用世界上最好的全彩色自动描摹器&#xff0c;能够将JPG、PNG、BMP和GIF等位图图像…...

Window部署Oracle并实现公网环境远程访问本地数据库

文章目录 前言1. 数据库搭建2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射 3. 公网远程访问4. 配置固定TCP端口地址4.1 保留一个固定的公网TCP端口地址4.2 配置固定公网TCP端口地址4.3 测试使用固定TCP端口地址远程Oracle 前言 Oracle&#xff0c;是甲骨文公司的一款关系…...

灵魂指针,教给(三)

欢迎来到白刘的领域 Miracle_86.-CSDN博客 系列专栏 C语言知识 先赞后看&#xff0c;已成习惯 创作不易&#xff0c;多多支持&#xff01; 目录 一、 字符指针变量 二、数组指针变量 2.1 数组指针变量是什么 2.2 数组指针变量如何初始化 三、二维数组传参本质 四、函数…...

纯手工搭建一个springboot maven项目

前言&#xff1a;idea社区版无法自动搭建项目&#xff0c;手动搭建的经验分享如下&#xff1a; 1 包结构 参考下图&#xff1a; 2 项目结构 3 maven依赖 具体的项目包结构如下图&#xff1a; 依据这个项目包结构配置一个springboot 的 pom依赖&#xff1a; <?xml ve…...

【Java】使用`LinkedList`类来实现一个队列,并通过继承`AbstractQueue`或者实现`Queue`接口来实现自定义队列

使用LinkedList类来实现一个队列&#xff0c;并通过继承AbstractQueue或者实现Queue接口来实现自定义队列。 以下是一个简单的示例&#xff0c;其中队列的大小与另一个List的容量保持一致&#xff1a; import java.util.LinkedList; import java.util.List; import java.util…...

ChatGPT消息发不出去了?我找到解决方案了

现象 今天忽然发现 ChatGPT无法发送消息&#xff0c;能查看历史对话&#xff0c;但是无法发送消息。 猜测原因 出现这个问题的各位&#xff0c;应该都是点击登录后顶部弹窗邀请[加入多语言 alapha 测试]了&#xff0c;并且语言选择了中文&#xff0c;抓包看到ab.chatgpt.com…...

《量子计算:下一个大风口,还是一个热炒概念?》

引言 量子计算,作为一项颠覆性的技术,一直以来备受关注。它被认为是未来计算领域的一次革命,可能改变我们对计算能力和数据处理的理解。然而,随着技术的不断进步和商业应用的探索,人们开始思考,量子计算到底是一个即将到来的大风口,还是一个被过度炒作的概念? 量子计…...

在Ubuntu中如何基于conda安装jupyterlab

在Ubuntu中如何创建ipykernel 可以用下面命令完成 conda create -n newenv python3.8conda activate enwenvconda install ipykernel5.1.4conda install ipython_genutilsipython -m ipykernel install --user --namepython3 --display-name Python3conda install -c conda-fo…...

Unity 中的 PlayFab 入门

要开始在 Unity 中使用 PlayFab,你只需执行以下两个简单步骤即可。第一步是设置 PlayFab 帐户。第二步是通过安装 Unity 编辑器扩展将其连接到 Unity。或者,你也可以下载 PlayFab SDK 并在没有扩展的情况下进行配置。 设置你的 PlayFab 帐户 访问 PlayFab 的网站并创建你的…...

常见排序算法(C++)

评判一个排序算法时除了时间复杂度和空间复杂度之外还要考虑对cache的捕获效果如何&#xff0c;cache友好的排序算法应该对数据的访问相对集中&#xff0c;快速排序相较于堆排序优点就是在于对cache的捕获效果好。 堆排序 时间复杂度&#xff1a;O&#xff08;n log n &#xf…...

多线程编程互斥锁mutex的创建

在Linux下的多线程编程中&#xff0c;互斥锁&#xff08;mutex&#xff09;的创建主要有两种方式&#xff1a;静态分配和动态分配。这两种方式的主要区别在于互斥锁的生命周期和初始化方式。 静态分配&#xff08;静态方式&#xff09; 静态分配方式是在程序编译时就已经确定互…...

在 SpringBoot3 中使用 Mybatis-Plus 报错

在 SpringBoot3 中使用 Mybatis-Plus 报错 Property ‘sqlSessionFactory’ or ‘sqlSessionTemplate’ are required Caused by: java.lang.IllegalArgumentException: Property sqlSessionFactory or sqlSessionTemplate are requiredat org.springframework.util.Assert.no…...

【libwebrtc】基于m114的构建

libwebrtc A C++ wrapper for binary release, mainly used for flutter-webrtc desktop (windows, linux, embedded).是 基于m114版本的webrtc 最新(20240309 ) 的是m122了。官方给出的构建过程 .gclient 文件 solutions = [{"name" : src,"url...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...

tomcat指定使用的jdk版本

说明 有时候需要对tomcat配置指定的jdk版本号&#xff0c;此时&#xff0c;我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...