news 2026/4/3 6:29:20

KMP算法详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
KMP算法详解

KMP算法用于实现字符串匹配问题。例如查找某个字符串是否是s的子串。

我们先来看一道题

一.力扣28.找出字符串中第一个匹配项的下标

给你两个字符串haystackneedle,请你在haystack字符串中找出needle字符串的第一个匹配项的下标(下标从 0 开始)。如果needle不是haystack的一部分,则返回-1

输入:haystack = "sadbutsad", needle = "sad"输出:0解释:"sad" 在下标 0 和 6 处匹配。 第一个匹配项的下标是 0 ,所以返回 0 。

对于这种题目,我们首先想到的就是使用两个for循环,依次找每一种可能,看看能不能找到匹配的字符串

1.传统for循环

思路:

  • 将主串T(长度为n)与模式串P(长度为m)依次对齐比较。

  • 对齐位置i从 0 到n-m,每次比较T[i..i+m-1]P[0..m-1]

  • 若某个字符不匹配,则模式串向右移动1 位,重新从头比较。

class Solution { public: int strStr(string haystack, string needle) { int n = haystack.length(); int m = needle.length(); // needle 为空字符串的情况 if (m == 0) return 0; // 主循环,尝试所有可能的起始位置 for (int i = 0; i <= n - m; i++) { int j; // 检查当前位置是否匹配 for (j = 0; j < m; j++) { if (haystack[i + j] != needle[j]) { break; } } // 如果完全匹配 if (j == m) { return i; } } //没找到就返回-1 return -1; } };

这种传统解法的时间复杂度是O(n*m),n和m分别是两个字符串的长度,对于最坏的情况,需要搜索n*m次.

那我们可不可以进行优化呢,让搜索的次数减少,以此来降低时间复杂度,当然可以,这就是KMP算法的思想

2.KMP算法

①什么是KMP算法

KMP算法用于实现字符串匹配问题。例如查找某个字符串是否是s的子串。普通方法是从s字符串的开头开始一次比较。时间复杂度O(n*m)。KMP该是该方法的优化方法

KMP算法的核心思想,就是每次如果字符串没有匹配成功,不是从头开始重新查找,而是从一个特定的合理位置开始继续查找,减少了查找次数

那我们应该如何去找到这个特定的合理位置呢,这就是KMP算法的关键,引入一个前缀表的概念

②前缀表

前缀表:记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀。

前缀是指不包含最后一个字符,以第一个字符开头的连续子串。

后缀是指不包含第一个字符,以最后一个字符结尾的连续子串

前缀表要求的就是相同前后缀的长度

字符串a的最长相等前后缀为0。 字符串aa的最长相等前后缀为1。 字符串aaa的最长相等前后缀为2。

③next数组

KMP算法就是把子串中的每个位置对应的最长相同前后缀长度,记录在next数组中,一旦匹配失败,就从当前已匹配位置的最长前缀长度继续进行匹配(next[i-1])

④代码实现

1)构建next数组

构建next数组的过程,实际上就是子串自己进行KMP算法的过程

void getNext(vector<int>& next, string& needle) { //初始化最大前后缀长度 int j = 0; //第一个位置的字母相同前后缀长度是0 next[0] = 0; //开始循环查找 for (int i = 1;i < needle.size();i++) { //如果不同,就从已经匹配的最大位置开始重新匹配,直到匹配成功 while (j > 0 && needle[i] != needle[j]) { j = next[j - 1]; } //如果相同,就将前后缀长度+1 if (needle[i] == needle[j]) { j++; } //给当前位置赋值 next[i] = j; } }
2)查找第一个匹配项位置
int KMP(string s, string s1) { //字符串为空或者子串长度更大都是错误的 if (s1.size() == 0 || s.size() == 0 || s.size() < s1.size()) { return -1; } //初始化next数组 vector<int>next(s1.size(),0); //调用方法得到next数组 getNext(next, s1); //开始查找 int j = 0; for (int i = 0;i < s.size();i++) { //和构建next数组一样,如果不匹配,就从已匹配的最长位置重新开始 while (j > 0 && s[i] != s1[j]) { j = next[j - 1]; } //如果相同,就将已匹配长度+1 if (s[i] == s1[j]) { j++; } //终止条件是已匹配长度和子串长度相等,说明全部匹配 if (j == s1.size()) { return i - s1.size() + 1; } } return -1; }
3)举一反三

如果题目要求查找所有匹配项,就将KMP函数中查找成功的部分改为

vec.push_back(i - s1.size() + 1);//存储结果 j=next[j-1];//继续查找
4)效率分析

对于传统的双重for循环的O(n*m)的时间复杂度,KMP算法可以将其降至O(n+m),大大优化了传统方法

在最坏的情况下,如子串是ac,父串是aaa...ac时效果更加明显

3.方法比较

算法时间复杂度空间复杂度优点缺点
暴力匹配O(n × m)O(1)实现简单,代码短最坏情况下效率低
KMPO(n + m)O(m)效率高,适合长字符串实现复杂,需要额外空间

二.KMP算法小结

  • 核心是最长公共前后缀(LPS),用于跳过已匹配部分。

  • next数组是预处理的移位/变形。

  • 匹配时主串指针不回退,模式串指针根据next回退。

  • 适合在流式文本中匹配,因为不需要全文存储。

KMP算法属于比较抽象难想的算法,建议画一画,模拟一下整个过程来帮助理解

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/16 3:09:09

5分钟部署Meta-Llama-3-8B-Instruct,vLLM+WebUI打造高效对话应用

5分钟部署Meta-Llama-3-8B-Instruct&#xff0c;vLLMWebUI打造高效对话应用 1. 引言&#xff1a;为什么选择 Meta-Llama-3-8B-Instruct&#xff1f; 在当前大模型快速发展的背景下&#xff0c;如何以低成本、高效率的方式部署一个具备强大对话能力的本地化AI助手&#xff0c;…

作者头像 李华
网站建设 2026/4/3 4:47:32

GPT-OSS-20B支持多种格式?实测GGUF和GPTQ兼容性

GPT-OSS-20B支持多种格式&#xff1f;实测GGUF和GPTQ兼容性 你是否也曾因为显存不足而放弃本地部署大模型的念头&#xff1f;面对动辄48GB显存需求的20B级模型&#xff0c;普通用户似乎只能望而却步。然而&#xff0c;随着GPT-OSS-20B的发布及其对多种量化格式的支持&#xff…

作者头像 李华
网站建设 2026/4/3 4:52:39

Qwen_Image_Cute_Animal_For_Kids创意教程:制作儿童徽章的步骤

Qwen_Image_Cute_Animal_For_Kids创意教程&#xff1a;制作儿童徽章的步骤 1. 技术背景与应用场景 在儿童教育、亲子互动和创意手工领域&#xff0c;个性化视觉内容的需求日益增长。传统的图片设计方式往往依赖专业美工或复杂的设计软件&#xff0c;难以满足快速生成、风格统…

作者头像 李华
网站建设 2026/3/24 19:38:51

从0开始学人脸修复,GPEN镜像助你快速入门CV项目

从0开始学人脸修复&#xff0c;GPEN镜像助你快速入门CV项目 1. 引言&#xff1a;为什么选择GPEN进行人像修复&#xff1f; 在计算机视觉&#xff08;CV&#xff09;领域&#xff0c;人脸图像的高质量恢复一直是极具挑战性的任务。尤其是在低分辨率、模糊或严重退化的图像中&a…

作者头像 李华
网站建设 2026/4/3 3:21:06

体验语音检测入门必看:云端按需付费成主流,1块钱起步

体验语音检测入门必看&#xff1a;云端按需付费成主流&#xff0c;1块钱起步 你是不是也和我一样&#xff0c;是个刚毕业的应届生&#xff0c;想转行进入AI领域&#xff1f;最近在刷招聘网站时&#xff0c;发现很多AI语音相关的岗位都写着“熟悉VAD技术”、“具备语音端点检测…

作者头像 李华
网站建设 2026/3/31 9:28:23

Emotion2Vec+ Large情感表达明显?弱情绪增强识别策略

Emotion2Vec Large情感表达明显&#xff1f;弱情绪增强识别策略 1. 引言&#xff1a;语音情感识别的挑战与Emotion2Vec Large的定位 在人机交互、智能客服、心理评估等应用场景中&#xff0c;语音情感识别&#xff08;Speech Emotion Recognition, SER&#xff09; 正逐渐成为…

作者头像 李华