KMP 算法中 next 数组的构建函数 get_next
KMP 算法中 next
数组的构建函数 get_next
,负责计算模式串的 next
数组,核心是通过递推找到每个位置的 “最长相等前缀后缀长度”。(下标从 1 开始):
一、函数作用
get_next(SString T, int next[])
的任务:
为模式串 T
生成 next
数组,next[i]
表示 模式串中第 i
个字符失配时,应该回退到的位置(本质是 “前 i-1
个字符的最长相等前缀后缀长度”)。
二、代码逐行解析
void get_next(SString T, int next[]) {// 初始化:// i:模式串当前处理到的位置(从 1 开始,对应字符 T.ch[1])// j:记录当前最长相等前缀后缀的长度(初始为 0,对应“没有前缀”)i = 1; j = 0; // next[1] 固定为 0(模式串第一个字符失配时,没有前缀可回退,特殊处理)next[1] = 0; // 循环条件:i 遍历模式串的每个字符(直到模式串末尾)while (i < T.length) { // 情况 1:j=0(回到起点) 或 当前字符匹配(T.ch[i] == T.ch[j])if (j == 0 || T.ch[i] == T.ch[j]) { // i、j 同时后移,扩展匹配长度++i; ++j; // 记录 next[i]:当前最长相等前缀后缀长度是 jnext[i] = j; } // 情况 2:当前字符不匹配(T.ch[i] != T.ch[j])else { // j 回退到 next[j](找更短的前缀后缀继续匹配)j = next[j]; }}
}
三、核心逻辑拆解(结合递推思想)
-
初始化:
i=1
从模式串第二个字符开始(第一个字符next[1]=0
已固定)。j=0
表示 “当前没有匹配的前缀”。
-
循环处理每个字符:
-
匹配时(
T.ch[i] == T.ch[j]
):
i
和j
同时后移,next[i] = j
表示 “前i
个字符的最长相等前缀后缀长度是j
”。
例:模式串ababc
,当i=3
(字符a
)、j=1
(字符a
)匹配时,i++=4
,j++=2
,next[4]=2
(前 4 个字符abab
的最长相等前缀后缀是ab
,长度 2)。 -
失配时(
T.ch[i] != T.ch[j]
):
j = next[j]
让j
回退到更短的前缀位置,继续尝试匹配。
例:模式串ababc
,若i=5
(字符c
)、j=3
(字符a
)失配,j = next[3] = 1
(回退到更短的前缀),再比较T.ch[5]
和T.ch[1]
。
-
四、对于i,j可能不见名知意,有点混乱,那下面将它们换掉 ,并再次进行解释
①、重命名变量后的代码(下标从 1 开始)
// 生成模式串 T 的 next 数组
// next[position] 表示:当模式串在 position 位置失配时,应回退到的位置
void get_next(SString T, int next[]) {// current_pos:当前处理到模式串的哪个位置(初始从第二个字符开始)int current_pos = 1;// prefix_len:当前最长相等前缀的长度(初始为 0,表示无前缀)int prefix_len = 0;// 第一个字符失配时,只能回退到模式串开头(下标 0,实际代码中用 0 表示)next[1] = 0;// 遍历模式串的每个字符(从第二个开始,直到末尾)while (current_pos < T.length) {// 情况 1:prefix_len 回退到 0(回到起点),或者当前字符匹配成功if (prefix_len == 0 || T.ch[current_pos] == T.ch[prefix_len]) {// 继续匹配下一个字符current_pos++;prefix_len++;// 记录:当匹配到 current_pos 位置失配时,应回退到 prefix_len 位置next[current_pos] = prefix_len;}// 情况 2:当前字符匹配失败else {// 回退 prefix_len 到更短的前缀位置,继续尝试匹配prefix_len = next[prefix_len];}}
}
②、关键变量解释
原变量 | 新变量 | 含义 |
---|---|---|
i | current_pos | 当前处理到模式串的哪个位置(对应字符 T.ch[current_pos] ) |
j | prefix_len | 当前最长相等前缀的长度,也表示前缀的下一个待匹配位置(T.ch[prefix_len] ) |
next | next | 核心数组,next[pos] 表示模式串在 pos 位置失配时应回退到的位置 |
③、核心逻辑拆解(带例子)
以模式串 T = "ABABC"
(下标从 1 开始)为例,逐步推导 next
数组:
1. 初始化
current_pos = 1; // 处理第 1 个字符 'A'
prefix_len = 0; // 无前缀
next[1] = 0; // 第一个字符失配时,回退到 0(实际逻辑中表示从头开始)
2. 处理 current_pos = 1
(字符 A
)
prefix_len = 0
→ 进入if
分支:current_pos++; // 2 prefix_len++; // 1 next[2] = 1; // 表示:当匹配到第 2 个字符失配时,应回退到第 1 个字符
3. 处理 current_pos = 2
(字符 B
)
T.ch[2] = 'B'
,T.ch[1] = 'A'
→ 不匹配 → 进入else
分支:prefix_len = next[1] = 0; // 回退到 0
- 再次循环:
prefix_len = 0
→ 进入if
分支:current_pos++; // 3 prefix_len++; // 1 next[3] = 1; // 表示:当匹配到第 3 个字符失配时,应回退到第 1 个字符
4. 处理 current_pos = 3
(字符 A
)
T.ch[3] = 'A'
,T.ch[1] = 'A'
→ 匹配 → 进入if
分支:current_pos++; // 4 prefix_len++; // 2 next[4] = 2; // 表示:当匹配到第 4 个字符失配时,应回退到第 2 个字符
5. 处理 current_pos = 4
(字符 B
)
T.ch[4] = 'B'
,T.ch[2] = 'B'
→ 匹配 → 进入if
分支:current_pos++; // 5 prefix_len++; // 3 next[5] = 3; // 表示:当匹配到第 5 个字符失配时,应回退到第 3 个字符
四、总结
get_next
函数的核心逻辑:
- 匹配成功:扩展当前前缀长度,并记录
next
值。 - 匹配失败:回退到更短的前缀位置(通过
next
数组),继续尝试匹配。
相关文章:
KMP 算法中 next 数组的构建函数 get_next
KMP 算法中 next 数组的构建函数 get_next ,负责计算模式串的 next 数组,核心是通过递推找到每个位置的 “最长相等前缀后缀长度”。(下标从 1 开始): 一、函数作用 get_next(SString T, int next[]) 的任务…...

IDEA 开发PHP配置调试插件XDebug
1、安装PHP环境 为了方便,使用的PhpStudy。 安装路径:D:\resources\phpstudy_pro\Extensions\php\php7.3.4nts 2、下载Xdebug Xdebug: Downloads 选择对应的版本下载,本次使用的是7.3。 3、配置Xdebug 在php.ini中添加Xdebug配置。 D…...

奇异值分解(SVD):线性代数在AI大模型中的核心工具
🧑 博主简介:CSDN博客专家、CSDN平台优质创作者,高级开发工程师,数学专业,10年以上C/C, C#, Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C、C#等开发语言,熟悉Java常用开…...
矩阵分解相关知识点总结(二)
文章目录 三、矩阵的QR分解3.1、Givens矩阵与Givens变换3.2、Householder矩阵与Householder变换3.3、QR分解 书接上文矩阵分解相关知识点总结(一) 三、矩阵的QR分解 3.1、Givens矩阵与Givens变换 设非零列向量 x ∈ R n \bm{x}\in {\bf{R}}^n x∈Rn及单…...

MySQL——视图 用户管理 语言访问
目录 视图 用户管理 数据库权限 访问 准备工作 使用函数 mysql界面级工具 连接池 视图 这里的视图与事务中的读视图是两个不同的概念:视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。视图的…...

二、Sqoop 详细安装部署教程
作者:IvanCodes 日期:2025年6月2日 专栏:Sqoop教程 Apache Sqoop 是一个强大的工具,用于在 Hadoop (HDFS, Hive, HBase) 与关系型数据库 (如 MySQL, PostgreSQL, Oracle) 之间高效传输数据。本教程将详细指导您如何根据官方网站截…...
用Python开启游戏开发之旅
在当今丰富多彩的数字娱乐世界中,游戏以其独特的魅力吸引着无数人的目光。而Python这门功能强大又简洁易懂的编程语言,也为游戏开发打开了一扇充满创意的大门。 一、选择Python的理由 Python之所以备受游戏开发者青睐,有诸多原因。其一&#…...
React 第五十四节 Router中useRevalidator的使用详解及案例分析
前言 useRevalidator 是 React Router v6.4 引入的一个强大钩子,用于在数据路由(Data Router)中手动触发路由数据的重新验证(revalidation)。 它在需要主动刷新数据而不改变路由位置的场景中非常有用。 一、useReval…...

【C语言预处理详解(下)】--#和##运算符,命名约定,命令行定义 ,#undef,条件编译,头文件的包含,嵌套文件包含,其他预处理指令
目录 五.#和##运算符 5.1--#运算符 5.2--##运算符 六.命名约定,#undef,命令行定义 6.1--命名约定 6.2--#undef 6.3--命名行定义 七.条件编译 常见的条件编译指令: 1.普通的条件编译: 2.多个分支的条件编译(可以利用条…...

03.搭建K8S集群
K8S集群搭建的方式 目前主流的搭建k8s集群的方式有kubeadm、minikube、二进制包三种方式: kubeadm(本案例搭建方式) 是一个工具,用于快速搭建kubernetes集群,目前应该是比较方便和推荐的,简单易用 kubea…...

RDMA简介3之四种子协议对比
RDMA协议共有四种子协议,分别为InfiniBand、iWARP、RoCE v1和RoCE v2协议。这四种协议使用统一的RDMA API,但在具体的网络层级实现上有所不同,如图1所示,接下来将分别介绍这四种子协议。 图1 RDMA四种子协议网络层级关系图 Infin…...

【最新版】西陆洗车系统源码全开源+uniapp前端+搭建教程
一.系统介绍 一款基于ThinkPHPUniapp开发的多门店洗车系统,包含用户端(小程序)、门店员工端(小程序)、门店端(PC)、平台管理端(PC)。 门店分连锁门店和独立门店…...
力扣LeetBook数组和字符串--二维数组
1.旋转矩阵 题目链接 想了那么久的各种旋转,对角线,其实把问题搞复杂了。 旋转90度的本质无非就是转置镜像对称 转置是什么?:将矩阵的行和列互换。 镜像对称:把矩阵从中间对折,互换位置 矩阵 A A [ 1 3 0…...

Linux开发工具(apt,vim,gcc)
目录 yum/apt包管理器 Linux编辑器 vim 1.见一见vim 2.vim的多模式 3.命令模式底行模式等 4.vim的配置 Linux编译器 gcc/g 1.预处理(宏替换) 2.编译(生成汇编) 3.汇编(生成机器可识别代码) 4.连…...
C# ExcelWorksheet 贴图
C# ExcelWorksheet 贴图 在C#中,如果你想在Excel工作表中插入图片(例如,在ExcelWorksheet中贴图),你可以使用ClosedXML或EPPlus这样的库来操作Excel文件。下面我将分别介绍如何使用这两个库来实现这一功能。 使用ClosedXML 首先,确保你已经安装了ClosedXML包。你可以通…...

鸿蒙Next开发真机调试签名申请流程
背景: 在学习鸿蒙next开发应用的初期总是会遇到一堆的问题,毕竟鸿蒙next开发不管是他的ArKTS语言还是他的开发工具DevEco Studio都还在起步阶段,就像当初的Android起步一样,总会有资料不足的一些问题。就比如我们学习下载完DevEco…...

[yolov11改进系列]基于yolov11引入上下文锚点注意力CAA的python源码+训练源码
【CAA介绍】 本文记录的是基于CAA注意力模块的RT-DETR目标检测改进方法研究。在远程遥感图像或其他大尺度变化的图像中目标检测任务中,为准确提取其长距离上下文信息,需要解决大目标尺度变化和多样上下文信息时的不足的问题。CAA能够有效捕捉长距离依赖…...
【Elasticsearch】 查询优化方式
在优化Elasticsearch的查询性能时,可以从多个维度着手,包括索引设计、查询优化、集群配置、数据管理以及监控分析等。常见的优化方式和策略有以下几种: 一、索引优化 合理设计字段类型: 字段类型选择: 对于不需要分词的…...
Xcode 16.4 + iOS 18 系统运行时崩溃:___cxa_current_primary_exception 符号丢失的原因与解决方案
在使用 Xcode 16.4 构建项目,运行到 iOS 18.3 或更早版本系统(包括模拟器)时,出现了如下的运行时崩溃: dyld[22183]: Symbol not found: ___cxa_current_primary_exceptionReferenced from: /.../WidgetOn.app/Widget…...

【linux】全志Tina预编译一个so库文件到根文件系统/usr/lib/下
一、sdk中新建文件夹 路径: V:\t113\work3\t113\openwrt\package\feeds\libs\md5util md5util为需要注入的库文件夹。 文件结构 libs md5util files libmd5util.so makefile etc.. 二、编写makefile include $(TOPDIR)/rules.mkPKG_NAME : md5util PKG_VERSIO…...

C# 类和继承(成员访回修饰符)
成员访回修饰符 本章之前的两节阐述了类的可访问性。对类的可访问性,只有两种修饰符:internal和public。 本节阐述成员的可访问性。类的可访问性描述了类的可见性;成员的可访问性描述了类成员的可 见性。 声明在类中的每个成员对系统的不同…...
c++ stl容器之map用法
目录 (1)map介绍 (2)map、multimap、unordered_map区别 (3)map用法 1.map接口表 2.使用举例 插入数据与遍历数据 查找关键字和值 删除元素 按照值排序 (4)multimap用法 &…...

Linux-文件管理及归档压缩
1.根下的目录作用说明: /:Linux系统中所有的文件都在根下/bin:(二进制命令目录)存放常用的用户命令/boot:系统启动时的引导文件(内核的引导配置文件,grub配置文件,内核配置文件) 例…...
结合Jenkins、Docker和Kubernetes等主流工具,部署Spring Boot自动化实战指南
基于最佳实践的Spring Boot自动化部署实战指南,结合Jenkins、Docker和Kubernetes等主流工具,提供从环境搭建到生产部署的完整流程: 一、环境准备与工具选型 1.基础设施 Jenkins服务器:安装Jenkins LTS版本,配置JDK(推荐JDK 11+)及Maven/Gradle插…...

微软认证考试科目众多?该如何选择?
在云计算、人工智能、数据分析等技术快速发展的今天,微软认证(Microsoft Certification)已成为IT从业者、开发者、数据分析师提升竞争力的重要凭证。但面对众多考试科目,很多人不知道如何选择。本文将详细介绍微软认证的考试方向、…...
MCP协议在LLM系统中的架构与实现原理研究
MCP协议的角色和功能定位 模型上下文协议(Model Context Protocol, MCP) 是由Anthropic公司(Claude模型的发布方)提出的一种开放协议,旨在标准化大型语言模型(LLM)与外部数据源、工具和服务之间的交互方式。可以将MCP类比为AI应用的“USB-C接口”:通过统一的接口协议,…...

Dify工作流实践—根据word需求文档编写测试用例到Excel中
前言 这篇文章依赖到的操作可查阅我之前的文章: dify里的大模型是怎么添加进来的:在Windows本地部署Dify详细操作 flask 框架app.route()函数的开发和调用:PythonWeb开发框架—Flask工程创建和app.route使用详解 结构化提示词的编写&…...

【LC实战派】小智固件编译
这篇写给立创吴总,是节前答应他配合git代码的说明;也给所有对小智感兴趣的小伙伴。 请多提意见,让这份文档更有价值 - 第一当然是拉取源码 - git clone https://github.com/78/xiaozhi-esp32.git 完成后,先查看固件中实际的…...
HTTP(超文本传输协议)详解
目录 一、基本概念 二、HTTP报文(结构) (一) 请求报文 (二) 响应报文 三、HTTP请求方法 1. GET方法 2. POST方法 3. PUT方法 4. HEAD方法 5. DELETE 6. OPTIONS 一、知识扩展 7. TRACE 8. CONNECT 四、HTTP持久通信 (一) HTTP keep-alive…...
Unity安卓平台开发,启动app并传参
using UnityEngine; using System;public class IntentReceiver : MonoBehaviour {public bool isVR1;void Start(){Debug.LogError("app1111111111111111111111111");if (isVR1){LaunchAnotherApp("com.HappyMaster.DaKongJianVR2");}else{// 检查是否有传…...