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

别再死记硬背Next数组了!用‘最长相等前后缀’这个核心概念,5分钟彻底搞懂KMP

从几何视角彻底理解KMP算法Next数组的本质是字符串的自相似性每次看到KMP算法中那个神秘的Next数组总有种面对黑盒的感觉——明明代码只有几行背后的逻辑却像被施了魔法。今天我们不谈公式推导换个视角用最长相等前后缀这个核心概念带你用几何化的方式重新认识KMP。你会发现Next数组不过是字符串自我相似性的数学表达而jNext[j]这个操作本质上是在利用已经匹配的部分中隐藏的对称性。1. 重新定义问题字符串匹配的几何意义想象你面前有两把标尺上方是文本串S下方是模式串P。传统的暴力匹配就像是将两把尺子从头到尾滑动比对每次失配就把下面的尺子向右移动一格。这种方法的低效在于它完全忽视了已经匹配部分蕴含的信息。KMP算法的精妙之处在于它发现模式串自身具有某种自相似性——就像分形图案中部分与整体的相似关系。这种相似性体现在字符串的某个前缀可能同时是该字符串的后缀。例如字符串ababa长度为1的前缀a与后缀a相同长度为3的前缀aba与后缀aba相同这种自相似结构可以用下面的图示表示a b a b a └─┘ └─┘ (长度为1的相等前后缀) └───┘ └───┘ (长度为3的相等前后缀)当我们用这个模式串匹配文本时如果在某个位置失败最聪明的做法不是从头开始而是找到已经匹配部分中最大的自相似段直接将模式串对齐到这个位置继续比较。这就是Next数组要记录的信息。2. Next数组的直观构建寻找字符串的对称轴Next数组的正式定义是对于模式串P的位置jNext[j]表示子串P[0..j-1]中最长相等前后缀的长度。这个定义听起来抽象但用几何视角看就非常直观——它测量的是字符串的对称程度。让我们以模式串ababaca为例手工构建Next数组j0空串人为规定Next[0]-1哨兵值j1子串a → 无真前后缀 → Next[1]0j2子串ab → 前缀[a]后缀[b] → 无匹配 → Next[2]0j3子串aba →前缀[a,ab]后缀[ba,a] → 最大匹配a → Next[3]1j4子串abab →前缀[a,ab,aba]后缀[bab,ab,b] → 最大匹配ab → Next[4]2j5子串ababa →前缀[a,ab,aba,abab]后缀[baba,aba,ba,a] → 最大匹配aba → Next[5]3j6子串ababac →前缀[a,ab,aba,abab,ababa]后缀[babac,abac,bac,ac,c] → 无匹配 → Next[6]0最终得到的Next数组[-1, 0, 0, 1, 2, 3, 0]提示实际编码时可以通过递推高效计算Next数组但理解手工构建过程对掌握概念至关重要。3. 为什么jNext[j]不会漏解数学归纳法的视角这是KMP算法最令人困惑的部分——当字符不匹配时为什么可以直接将j回退到Next[j]而不需要检查中间位置我们可以用数学归纳法来证明这一点。归纳基础当j0时匹配失败显然需要将i前进相当于j回退到-1后执行j归纳假设假设对于所有小于当前j的位置jNext[j]的策略都是正确的归纳步骤在位置j匹配失败时我们已经确认P[0..j-1]与S[i-j..i-1]完全匹配Next[j]给出了P[0..j-1]的最大自相似长度k意味着P[0..k-1] P[j-k..j-1]因此可以直接将P的前k位P[0..k-1]对齐到S[i-k..i-1]这相当于设置jk由于P[0..k-1]已经与S[i-k..i-1]匹配我们只需要继续比较P[k]与S[i]这个过程中没有跳过任何可能的匹配位置因为任何中间对齐方式要么会导致不匹配由Next数组的定义保证要么对应一个更小的k值已经被Next数组排除。4. 优化Next数组构建避免不必要的比较标准的Next数组构建算法有一个潜在缺陷当P[j] P[Next[j]]时后续比较必然失败。例如模式串aaaab在j4时Next[4]3aaa的前后缀最大匹配但P[4]P[3]a所以当P[4]不匹配时P[3]也必然不匹配改进方法是构建Next数组时增加判断def build_next_optimized(p): next [0] * len(p) next[0] -1 j, k 0, -1 while j len(p) - 1: if k -1 or p[j] p[k]: j 1 k 1 next[j] k if p[j] ! p[k] else next[k] # 关键优化 else: k next[k] return next优化后的Next数组会跳过这些必然失败的比较将指针直接回退到更早的位置。对于上面的aaaab例子优化后的Next数组为[-1, -1, -1, -1, 3]避免了多余的比较。5. 从理论到实践完整的KMP算法实现结合上述理解我们可以写出完整的KMP算法def kmp_search(text, pattern): next build_next_optimized(pattern) i j 0 while i len(text) and j len(pattern): if j -1 or text[i] pattern[j]: i 1 j 1 else: j next[j] return i - j if j len(pattern) else -1时间复杂度分析构建Next数组O(m)匹配过程O(n)总体O(nm)相比之下暴力算法的O(nm)复杂度在长字符串场景下差距明显。例如在100万字符的文本中查找1000字符的模式KMP只需约100万次操作而暴力算法可能需要10亿次。6. 常见误区与调试技巧即使理解了原理实现KMP时仍容易陷入一些陷阱边界条件处理空字符串匹配模式串比文本串长多个匹配位置的情况Next数组构建错误忘记初始化Next[0]-1在优化版本中错误处理p[j]p[k]的情况匹配逻辑错误没有处理j-1的特殊情况循环条件设置不当导致越界调试时可以打印中间状态def debug_kmp(text, pattern): next build_next_optimized(pattern) print(Next数组:, next) i j 0 while i len(text) and j len(pattern): print(fi{i}, j{j}, 比较{text[i]}和{pattern[j]}) if j -1 or text[i] pattern[j]: i 1 j 1 else: j next[j] return i - j if j len(pattern) else -1理解KMP的关键在于将Next数组视为模式串的自相似性描述而匹配过程就是在利用这种自相似性智能地移动模式串。掌握了这个几何视角你就不再需要死记硬背算法步骤而是能够从第一性原理推导出整个算法。

相关文章:

别再死记硬背Next数组了!用‘最长相等前后缀’这个核心概念,5分钟彻底搞懂KMP

从几何视角彻底理解KMP算法:Next数组的本质是字符串的自相似性 每次看到KMP算法中那个神秘的Next数组,总有种面对黑盒的感觉——明明代码只有几行,背后的逻辑却像被施了魔法。今天我们不谈公式推导,换个视角用"最长相等前后缀…...

【代码】基于交替方向乘子法(admm)的微电网分布式低碳优化运行策略matlab-yalmip-cplex/gurobi

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…...

如何解决多线图中线条颜色不渲染(仅标记和提示框显示颜色)的问题

多线图中线条显示为黑色而标记点和工具提示却正常显示设定颜色,通常是因第三方 css 或 javascript 库意外覆盖了图表库的样式或破坏了其渲染逻辑所致。 多线图中线条显示为黑色而标记点和工具提示却正常显示设定颜色,通常是因第三方 css 或 javascr…...

CSS如何消除图片下方多余间隙_设置display-block改变盒模型

图片下方空白源于img默认inline导致的基线对齐&#xff1b;display:block最直接有效&#xff0c;vertical-align:middle等有兼容性与场景限制&#xff0c;font-size:0或line-height:0副作用大。图片下方空白是行内元素的基线对齐导致的默认情况下 <img> 是行内元素&#…...

自己做agent项目时,为什么工具和提示词写完之后总要重构再重构

最近有朋友来问我&#xff0c;他们团队做内部agent代理项目&#xff0c;工具写了十几个&#xff0c;能跑起来了&#xff0c;但后来想加权限没地方加&#xff0c;agent中断之后也不知道怎么恢复状态&#xff0c;最后只好停下来把工具全部重写了一遍&#xff01; 他们花了一个小…...

逆向YouTube Shorts接口:我是如何用Java和Protobuf搞定短视频列表解析的

逆向解析YouTube Shorts接口&#xff1a;Java与Protobuf实战指南 在移动应用逆向工程领域&#xff0c;Google系产品的接口分析向来以高复杂度著称。本文将分享如何突破层层技术障碍&#xff0c;从零开始解析YouTube Shorts短视频列表接口的全过程。不同于常见的API调用教程&…...

SAP财务凭证增强实战:利用BADI_ACC_DOCUMENT和CI_COBL为BAPI_ACC_DOCUMENT_POST扩展自定义字段

SAP财务凭证增强实战&#xff1a;从需求分析到稳定部署的全流程设计 在SAP标准财务模块实施过程中&#xff0c;业务需求的个性化往往超出标准功能的覆盖范围。当企业需要为会计凭证添加反记账标识、自定义记账码等特殊字段时&#xff0c;标准的BAPI_ACC_DOCUMENT_POST接口就显得…...

Akagi麻将AI助手:30天从新手到高手的终极免费指南

Akagi麻将AI助手&#xff1a;30天从新手到高手的终极免费指南 【免费下载链接】Akagi 支持雀魂、天鳳、麻雀一番街、天月麻將&#xff0c;能夠使用自定義的AI模型實時分析對局並給出建議&#xff0c;內建Mortal AI作為示例。 Supports Majsoul, Tenhou, Riichi City, Amatsuki,…...

SpringBoot+Vue教务管理系统源码+论文

代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339; 分享万套开题报告任务书答辩PPT模板 作者完整代码目录供你选择&#xff1a; 《SpringBoot网站项目》1800套 《SSM网站项目》1500套 《小程序项目》1600套 《APP项目》1500套 《Python网站项目》…...

如何配置Oracle 19c Data Pump目录_数据泵导入导出的环境准备

必须先创建DIRECTORY对象并授权&#xff1a;CREATE OR REPLACE DIRECTORY dpump_dir AS /u01/app/oracle/dpdump; GRANT READ,WRITE ON DIRECTORY dpump_dir TO scott; 且Oracle进程需有目录读写权限。怎么创建 Data Pump 目录对象&#xff08;DIRECTORY&#xff09;oracle dat…...

SpringBoot项目整合FISCO BCOS 2.9.1 SDK:从WeBASE-Front导出合约到Java调用的保姆级避坑指南

SpringBoot项目整合FISCO BCOS 2.9.1 SDK实战&#xff1a;从合约导出到Java调用的全流程解析 当Java开发者首次尝试将区块链能力整合到现有SpringBoot项目中时&#xff0c;往往会遇到一系列意料之外的挑战。本文将以一个典型的企业级资产管理系统为背景&#xff0c;详细拆解从W…...

C语言宏定义续行符踩坑实录:手把手教你解决‘backslash and newline separated by space’警告

C语言宏定义续行符的隐秘陷阱&#xff1a;从警告解析到工程级解决方案 第一次在CLion里看到backslash and newline separated by space这个警告时&#xff0c;我盯着那个无辜的反斜杠看了足足三分钟。作为一个刚接触C语言宏编程的开发者&#xff0c;这个看似简单的格式问题背后…...

UniApp实战:精准控制微信小程序iOS端滚动行为,告别橡皮筋回弹

1. 为什么iOS橡皮筋效果让人又爱又恨 第一次用UniApp开发微信小程序时&#xff0c;我就被iOS这个特性整懵了。明明在安卓机上运行正常的页面&#xff0c;到了iPhone上就变成了"橡皮泥"——随便一拉就能扯出大片空白。后来才知道&#xff0c;这正是iOS引以为傲的橡皮筋…...

HarmonyOS布局避坑指南:为什么你的Column和Row总对不齐?

HarmonyOS布局避坑指南&#xff1a;为什么你的Column和Row总对不齐&#xff1f; 在HarmonyOS应用开发中&#xff0c;布局是构建用户界面的基础。然而&#xff0c;许多开发者在实际项目中常常遇到Column和Row组件对不齐的问题&#xff0c;导致界面显示效果不尽如人意。本文将深入…...

别再只盯着K-Means了!用sklearn的轮廓系数(silhouette_score)帮你选出最佳聚类算法

用轮廓系数为聚类算法打分&#xff1a;从K-Means到DBSCAN的科学选择指南 当面对一堆未标注的数据时&#xff0c;很多人的第一反应是直接套用K-Means算法——这就像拿到食材只会做炒饭一样。但真实世界的数据分布千奇百怪&#xff0c;有的像瑞士奶酪布满空洞&#xff08;适合DBS…...

JavaScript 中的 setTimeout 是否依赖系统时钟?

settimeout 的延迟计时基于浏览器内部的高精度单调时钟&#xff08;如 performance.now() 所依赖的机制&#xff09;&#xff0c;而非操作系统本地时间&#xff1b;因此修改系统时间不会影响其倒计时行为&#xff0c;但页面休眠、cpu 节流或事件循环阻塞会导致实际触发延迟。 …...

科研党福音:Zotero 6.0 内置PDF阅读器+翻译插件,打造一站式文献阅读与笔记系统

Zotero 6.0 科研工作流革命&#xff1a;内置PDF生态与智能翻译实战指南 当你在深夜赶论文时&#xff0c;是否经历过这样的场景&#xff1a;PDF阅读器卡顿崩溃、翻译软件弹窗遮挡关键图表、文献批注散落在五个不同平台&#xff1f;Zotero 6.0的这次迭代&#xff0c;用原生PDF阅读…...

CTF新手必看:从猪圈密码到JSFuck,这10种古典密码的识别与破解实战

CTF密码学实战&#xff1a;10种古典密码的快速识别与高效破解指南 第一次参加CTF比赛时&#xff0c;我盯着那道Crypto题目发呆了半小时——密文由一堆点和横线组成&#xff0c;隐约像是某种编码&#xff0c;但完全无从下手。直到队友提醒"试试摩斯密码"&#xff0c;三…...

如何通过宝塔面板批量导出网站数据_使用宝塔命令行导出

宝塔命令行导出网站数据的正确入口是使用官方bt命令工具&#xff0c;通过bt 10&#xff08;网站备份&#xff09;或bt 11&#xff08;数据库备份&#xff09;子命令执行&#xff1b;需SSH登录root权限服务器&#xff0c;备份文件默认存于/www/backup/site/和/database/目录&…...

怎么部署OpenClaw?2026年华为云部署OpenClaw配置Coding Plan喂奶级流程

怎么部署OpenClaw&#xff1f;2026年华为云部署OpenClaw配置Coding Plan喂奶级流程。OpenClaw&#xff08;前身为Clawdbot/Moltbot&#xff09;作为开源、本地优先的AI助理框架&#xff0c;凭借724小时在线响应、多任务自动化执行、跨平台协同等核心能力&#xff0c;成为个人办…...

【AI Agent工程实战系列②】工具调用的正确姿势——不只是写个函数那么简单

先模拟一个场景 我们有一个Agent负责处理内部的IT工单,工具列表里有两个长得很像的工具: def get_user_info(user_id: str) -> dict:"""获取用户的基本信息"""...def get_user_permissions(user_id: str) -> dict:"""获…...

【AI Agent工程实战系列①】Agent系统为什么比你想的难十倍

Demo Agent和生产级Agent:本质区别在哪里 绝大多数Agent教程展示的是这样的系统: 用户输入 → LLM思考 → 选择工具 → 工具执行 → 返回结果这个流程在happy path(正常路径)上工作得很好。教程里的例子永远是: 用户问题清晰、意图明确 工具总是返回正确结果 任务在3-5步…...

OpCore Simplify:黑苹果配置终极指南 - 智能自动化工具让OpenCore EFI创建变得简单快速

OpCore Simplify&#xff1a;黑苹果配置终极指南 - 智能自动化工具让OpenCore EFI创建变得简单快速 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify Op…...

3步实现安卓投屏:QtScrcpy让你的手机在电脑上流畅操作

3步实现安卓投屏&#xff1a;QtScrcpy让你的手机在电脑上流畅操作 【免费下载链接】QtScrcpy Android实时投屏软件&#xff0c;此应用程序提供USB(或通过TCP/IP)连接的Android设备的显示和控制。它不需要任何root访问权限 项目地址: https://gitcode.com/barry-ran/QtScrcpy …...

保姆级教程:手把手调试vsomeip 3.1.20.3的Event订阅流程(附GDB/日志追踪技巧)

深入调试vsomeip事件订阅&#xff1a;从原理到实战排查指南 事件订阅机制的核心原理 vsomeip作为车载中间件领域的核心通信框架&#xff0c;其事件订阅机制的设计直接影响着分布式系统的实时性和可靠性。理解这套机制的工作原理&#xff0c;是高效排查订阅问题的前提。 事件订阅…...

Scroll Reverser:解决Mac滚动方向混乱的终极指南

Scroll Reverser&#xff1a;解决Mac滚动方向混乱的终极指南 【免费下载链接】Scroll-Reverser Per-device scrolling prefs on macOS. 项目地址: https://gitcode.com/gh_mirrors/sc/Scroll-Reverser 你是否经常在Mac触控板和鼠标之间切换时&#xff0c;被完全相反的滚…...

深入涂鸦IoT SDK核心:剖析pre_app_init到device_init的启动流程与最佳实践

涂鸦IoT SDK启动流程深度解析&#xff1a;从硬件上电到云端连接的架构设计与性能优化 在智能硬件开发领域&#xff0c;启动流程的优化往往决定了产品的第一印象。想象一下&#xff1a;当你按下智能灯泡的开关&#xff0c;是希望立即看到灯光响应&#xff0c;还是等待几秒才亮起…...

别再死记模块了!一张图看懂AUTOSAR CAN信号流:普通、诊断、XCP、NM报文到底怎么走?

AUTOSAR CAN信号流全景解析&#xff1a;从报文属性到配置落地的完整逻辑链 在汽车电子开发领域&#xff0c;AUTOSAR架构下的CAN通信配置一直是工程师们面临的难点之一。许多开发者虽然熟悉各个独立模块的功能&#xff0c;但当面对实际项目配置时&#xff0c;却常常陷入"只…...

别再死记硬背欧拉公式了!用Python可视化平面图,5分钟搞懂n-m+r=2

用Python可视化平面图&#xff1a;5分钟玩转欧拉公式的几何奥秘 第一次接触欧拉公式时&#xff0c;那个简洁的n-mr2让我既惊叹又困惑——为什么节点、边和面之间会存在如此精确的数学关系&#xff1f;直到我用代码亲手绘制出各种平面图&#xff0c;看着程序自动计算出的数值完…...

从‘救命稻草’到‘瑞士军刀’:嵌入式老鸟教你用U-Boot命令诊断与修复启动故障

嵌入式系统急救指南&#xff1a;U-Boot命令实战排错手册 当嵌入式设备卡在启动阶段&#xff0c;屏幕上的U-Boot提示符可能是你最后的救命稻草。作为嵌入式开发者&#xff0c;我曾无数次面对这样的场景&#xff1a;生产线上的设备突然无法启动&#xff0c;客户现场的系统莫名崩溃…...