GO语言实现KMP算法

前言

本文结合朱战立教授编著的《数据结构—使用c语言(第五版)》(以下简称为《数据结构(第五版)朱站立》)中4.4.2章节内容编写,KMP的相关概念可参考此书4.4.2章节内容。原文中代码是C语言,本文改用Go语言编写,逻辑不变。

一、KMP介绍

‌KMP算法‌(Knuth-Morris-Pratt算法)是一种高效的字符串匹配算法,由D.E.Knuth、J.H.Morris和V.R.Pratt提出。该算法的核心在于利用匹配失败后的信息,尽量减少模式串与主串的匹配次数,以达到快速匹配的目的。KMP算法的时间复杂度为O(m+n),其中m和n分别代表模式串和主串的长度。

二、求next数组

next数组是KMP算法中核心概念,求出next数组后,在模式串元素和主串元素比较的失败的时候,可以将模式串t直接偏移到以next数组中的元素为下标的位置,主串指针不偏移,减少了元素比较次数,下面我们直接求next数组

举例

字符串s=“ababbababcabac”
模式串t=“ababcab”
go语言版求next数组的代码如下:

func GetNext(s string) []int {var next []int = make([]int, len(s))next[0] = -1next[1] = 0// j表示当前要求next值的位置// k表示当前要和前一个字符比对的下标j, k := 1, 0for j < len(s)-1 {if s[j] == s[k] {next[j+1] = k + 1k++j++} else if k == 0 {next[j+1] = 0j++} else {k = next[k]}}return next
}

执行上面代码我们能获取到next数组如下:

PS D:\Project\GoWorkSpace\DataStructure> go run .\0113\KMP_Algorithm.go
[-1 0 0 1 2 0 1]

注:以上代码的变量名称,逻辑均与《数据结构(第五版)朱站立》中内容一致,方便代码阅读

三、图解KMP匹配过程

中间部分循环过程省略,主要看当模式串和主串不相等时,模式串如何偏移
字符串s=“ababbababcabac”
模式串t=“ababcab”
next数组=[-1 0 0 1 2 0 1]
在这里插入图片描述
第一步:s数组元素和t数组元素一一对比,如果成功两个数组下标偏移同时+1继续比较,以此类推
在这里插入图片描述
第二步:当s[4]≠t[4]时,next[4]=2,s数组不偏移,t数组偏移到t[2],比较s[4]和t[2]
在这里插入图片描述
第三步:当s[4]≠t[2]时,next[2]=0,s数组不偏移,t数组偏移到t[0],比较s[4]和t[0]
在这里插入图片描述
第四步:当s[4]≠t[0]时,由于t数组已经到第一位,所以s数组下标+1,比较s[5]和t[0]
在这里插入图片描述
第五步:当s[5]=t[0]时,回到了第一步,两个数组下标偏移同时+1继续比较,以此类推;当t的下标为7时s的下标为12,循环结束打印t的第一个元素在s中下标的位置,即:12-7=5

四、Go示例代码

package mainimport "fmt"func KMP(s string, t string) int {m := len(s)n := len(t)// s中当前比对的位置是i// t中当前比对的位置是ji, j := 0, 0next := GetNext(t)for i < m && j < n {if s[i] == t[j] {i++j++} else if j == 0 {i++} else {j = next[j] // t串偏移,偏移到next[j]下标}}if j == n { // t串全部匹配return i - j} else {return -1}
}
func GetNext(s string) []int {var next []int = make([]int, len(s))next[0] = -1next[1] = 0// j表示当前要求next值的位置// k表示当前要和前一个字符比对的下标j, k := 1, 0for j < len(s)-1 {if s[j] == s[k] {next[j+1] = k + 1k++j++} else if k == 0 {next[j+1] = 0j++} else {k = next[k]}}return next
}
func main() {t := "ababcab"fmt.Println(GetNext(t))fmt.Println(KMP("ababbababcabac", t))
}

运行结果

PS D:\Project\GoWorkSpace\DataStructure> go run .\0113\KMP_Algorithm.go
[-1 0 0 1 2 0 1]
5

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

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

相关文章

Windows核心编程—匿名管道双向通信

注&#xff1a;父进程要创建两个匿名管道&#xff0c;并且STARTUPINFO 里面的两个字段很重要 A进程 void CMFCApplication1Dlg::OnBnClickedButton1() {SECURITY_ATTRIBUTES sa {};sa.nLength sizeof(SECURITY_ATTRIBUTES);sa.bInheritHandle TRUE;CreatePipe(&m_hRead…

基于springboot+vue的洪涝灾害应急信息管理系统设计与实现

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

centos修改/etc/resolv.conf 重启network后又恢复到原来的状态

博主使用的是centos7 问题描述&#xff1a;centos修改/etc/resolv.conf 执行 service network restart 后&#xff0c;/etc/resolv.conf 又恢复到原来的状态 解决方法&#xff1a;/etc/resolv.conf 保存 DNS 是暂时的&#xff0c;当重新启动 network 时&#xff0c;/etc/resol…

MySQL:索引

目录 1.MySQL索引是干什么的 2.铺垫知识 3.单个page的理解 4.页目录 单页情况 多页情况 1.MySQL索引是干什么的 MySQL的索引是提高查询效率&#xff0c;主要提高海量数据的检索速度。 2.铺垫知识 操作系统与磁盘之间IO的基本单位是4kb。 数据库是一个应用层软件&#…

【微服务】面试题 5、分布式系统理论:CAP 与 BASE 详解

分布式系统理论&#xff1a;CAP 与 BASE 详解 一、CAP 定理 背景与定义&#xff1a;1998 年由加州大学科学家埃里克布鲁尔提出&#xff0c;分布式系统存在一致性&#xff08;Consistency&#xff09;、可用性&#xff08;Availability&#xff09;、分区容错性&#xff08;Part…

大数据技术Kafka详解 ⑤ | Kafka中的CAP机制

目录 1、分布式系统当中的CAP理论 1.1、CAP理论 1.2、Partitiontolerance 1.3、Consistency 1.4、Availability 2、Kafka中的CAP机制 C软件异常排查从入门到精通系列教程&#xff08;核心精品专栏&#xff0c;订阅量已达600多个&#xff0c;欢迎订阅&#xff0c;持续更新…

linux自动分区后devmappercentos-home删除后合并到其它分区上

删除其他分区&#xff0c;合并到对应分区上增加磁盘空间 删除开机默认挂载 /dev/mapper/centos-home vim /etc/fstab 把 /dev/mapper/centos-home 这一行删除掉命令行取消挂载 /dev/mapper/centos-home umount /dev/mapper/centos-home删除掉逻辑卷 home lvsdf -hlvremove /…

东芝3525AC彩色复印机复印默认成黑白模式方法

同样适用2010AC等机型 东芝3525AC彩色激光数码复合机基本参数 产品类型&#xff1a;激光数码复合机 颜色类型&#xff1a;彩色 速度类型&#xff1a;中速 复印速度&#xff1a;彩色&#xff1a;35cpm&#xff0c;黑白&#xff1a;35cpm 涵盖功能&#xff1a;复印/打印/扫描…

T-SQL编程

目录 1、T-SQL的元素 1.1 标识符 1. 常规标识符 2. 分隔标识符 1.2 变量 1. 全局变量 2. 局部变量 1.3 运算符 1. 算数运算符 2. 赋值运算符 3. 位运算符 4. 比较运算符 5. 逻辑运算符 6. 字符串连接运算符 7. 一元运算符 8. 运算符的优先级和结合性 1.4 批处…

SpringBoot-Day1

1.Springboot入门 创建Maven工程 导入spring-boot-stater-web起步依赖 编写Controller 提供启动类 2.yml配置信息书写与获取 书写 # 发件人信息 email:user: 172349823457qq.comcode: sajdajlwhjfgfkllwhost: smtp.qq.comauth: true ​ # 学生爱好 hobbies:- 打篮球- 踢…

【Linux】从零开始:编写你的第一个Linux进度条小程序

Linux相关知识点可以通过点击以下链接进行学习一起加油&#xff01;初识指令指令进阶权限管理yum包管理与vim编辑器GCC/G编译器make与Makefile自动化构建GDB调试器与Git版本控制工具 文章目录 一、知识铺垫1.1 回车与换行概念1.2 缓冲区 二、实现简单倒计时三、进度条3.1 Verrs…

【HarmonyOS之旅】基于ArkTS开发(二) -> UI开发二

目录 1 -> 声明式UI开发指导 1.1 -> 开发说明 1.2 -> 创建页面 1.3 -> 修改组件样式 1.4 -> 更新页面内容 2 -> 创建简单视图 2.1 -> 构建Stack布局 2.2 -> 构建Flex布局 2.3 -> 构建食物数据模型 2.4 -> 构建食物列表List布局 2.5 -…

【React】新建React项目

目录 create-react-app基础运用React核心依赖React 核心思想&#xff1a;数据驱动React 采用 MVC体系package.jsonindex.html好书推荐 官方提供了快速构建React 项目的脚手架&#xff1a; create-react-app &#xff0c;目前使用它安装默认是19版本&#xff0c;我们这里降为18…

分多个AndroidManifest.xml来控制项目编译

使用场景 公司项目和我的项目的AndroidManifest.xml混在一起&#xff0c;我需要区分开来编译观察app运行 1.在app/src/main/ 下写多个AndroidManifest.xml AndroidManifest.own.xmlAndroidManifest.com.xml 2.编写powershell脚本 第一对脚本com-build.ps1和reset-com-mani…

linux进程

课本概念&#xff1a;程序的⼀个执行实例&#xff0c;正在执行的程序等内核观点&#xff1a;担当分配系统资源&#xff08;CPU时间&#xff0c;内存&#xff09;的实体。 进程信息被放在一个叫做进程控制块的数据结构中&#xff0c;可以理解为进程属性的集合.课本上称之为PCB&…

Hadoop•安装JDK

听说这里是目录哦 创建目录❤️‍&#x1f525;上传JDK安装包&#x1f497;查看JDK是否上传成功&#x1f498;安装JDK&#x1f496;配置JDK系统环境变量&#x1f493;验证JDK是否安装成功&#x1f49e;分发JDK安装目录&#x1f48c;分发系统环境变量文件&#x1f49d;若显示没有…

[Deep Learning] Anaconda+CUDA+CuDNN+Pytorch(GPU)环境配置-2025

文章目录 [Deep Learning] AnacondaCUDACuDNNPytorch(GPU)环境配置-20250. 引子1. 安装Anaconda1.1 安装包下载&#xff1a;1.2 启用安装包安装1.3 配置(系统)环境变量1.4 验证Anaconda是否安装完毕1.5 Anaconda换源 2. 安装CUDACuDNN2.1 判断本机的CUDA版本2.2 下载适合自己CU…

网络原理(四)—— 网络层、数据链路层 与 DNS

网络层 网络层这里重点介绍 IP 协议&#xff0c;首先先解析 IP 数据包&#xff1a; 先介绍第一行&#xff1a; 4位版本号是指使用了哪一个版本的 IP 协议&#xff0c;这里有 IPV4 和 IPV6 两种协议&#xff0c;现在主要使用的是 IPV4 这一个版本号&#xff0c; IPV6 在国内也…

Redis快速入门店铺营业状态设置

Redis简介 Redis是一种基于内存的键值对&#xff08;K-V&#xff09;数据库。 这意味着它与MySQL数据库类似&#xff0c;都能够用于存储数据&#xff0c;但两者又有着本质的区别。首先两者存储数据的结构不一样&#xff0c;Redis通过键&#xff08;key&#xff09;和值…

Node.js 如何实现文件夹内文件批量重命名

文章目录 一、引言二、Node.js 简介2.1 是什么2.2 优势 三、Node.js 批量重命名原理3.1 涉及的核心模块3.2 关键函数 四、实战步骤4.1 环境搭建4.2 代码实现4.3 代码解释 五、案例分析5.1 场景描述5.2 解决方案 六、可能遇到的问题与解决方法6.1 常见错误6.2 解决方案 七、总结…