一文搞懂KMP算法!!!

这篇具有很好参考价值的文章主要介绍了一文搞懂KMP算法!!!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🍁什么是KMP算法?

  • KMP算法是一种改进的 字符串匹配算法,由 D.E.KnuthJ.H.MorrisV.R.Pratt 提出的,因此人们称它为 克努特—莫里斯—普拉特 操作(简称 KMP 算法)。
    • KMP 算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。
    • 具体实现就是通过一个 next() 数组实现,数组本身包含了模式串的局部匹配信息。KMP 算法的时间复杂度 O ( m + n ) O(m+n) O(m+n)

🍁什么是 next() 数组 和 前缀表?

next 数组就是一个前缀表(prefix table)!

前缀表有什么作用呢

前缀表是用来回退的,它记录了 模式串主串(文本串) 不匹配的时候,模式串 应该从哪里开始重新匹配。

我们来举一个例子:

  • 要在文本串aabaabaafa 中查找是否出现过一个模式串aabaaf

如动画所示

一文搞懂KMP算法!!!

最长公共前后缀

  • 字符串的前缀是:指不包含最后一个字符的所有 以第一个字符开头的连续子串
  • 后缀:是指不包含第一个字符的所有 以最后一个字符结尾的连续子串

正确理解什么是前缀什么是后缀很重要!
可以理解为最长相等前后缀

如何计算前缀表

注意字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串;后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。

  1. 长度为前1个字符的子串 a,最长相同前后缀的长度为 0

一文搞懂KMP算法!!!

  1. 长度为前2个字符的子串 aa ,最长相同前后缀的长度为 1

一文搞懂KMP算法!!!
3. 长度为前3个字符的子串 aab,最长相同前后缀的长度为 0

一文搞懂KMP算法!!!

  1. 以此类推: 长度为前4个字符的子串 aaba,最长相同前后缀的长度为 1
  2. 长度为前5个字符的子串aabaa,最长相同前后缀的长度为 2
  3. 长度为前6个字符的子串aabaaf,最长相同前后缀的长度为 0

一文搞懂KMP算法!!!

🚀 构造next数组

构造 next 数组其实就是计算 模式串 s

  • 定义两个指针 ijj 指向前缀末尾位置i 指向后缀末尾位置
  • next[i] 表示 i(包括 i )之前最长相等的前后缀长度(其实就是 j)。

next 数组就可以是前缀表,但是很多实现都是把 前缀表统一减一(右移一位,初始位置为 -1 )之后作为 next 数组。前缀表的构造过程,主要有如下三步:

  1. 初始化:
    • j 初始化为 -1;
  2. 处理前后缀不相同的情况
    • 因为 j 初始化为 -1,那么 i 就从1 开始,进行 s[i]s[j+1] 的比较;
    • 如果 s[i]s[j+1] 不相同,也就是遇到 前后缀末尾不相同的情况,就要向前回退。
      • next[j] 就是记录着 j(包括 j )之前的子串的相同前后缀的长度;
      • 那么 s[i]s[j+1] 不相同,就要找 j+1 前一个元素在 next 数组里的值(就是 next[j] )。
  3. 处理前后缀相同的情况
    • 如果 s[i]s[j + 1] 相同,那么就同时向后移动 ij 说明找到了相同的前后缀,同时还要将 j(前缀的长度)赋给 next[i] , 因为 next[i] 要记录相同前后缀的长度。

构造 next 数组的逻辑流程动画如下:
一文搞懂KMP算法!!!
构造 next 数组的函数如下:(C++)

void getNext(int* next, const string& s){
    int j = -1;
    next[0] = j;
    for(int i = 1; i < s.size(); i++) { // 注意i从1开始
        while (j >= 0 && s[i] != s[j + 1]) { // 前后缀不相同了
            j = next[j]; // 向前回退
        }
        if (s[i] == s[j + 1]) { // 找到相同的前后缀
            j++;
        }
        next[i] = j; // 将j(前缀的长度)赋给next[i]
    }
}

🚀 使用next数组来做匹配

在文本串 s 里找是否出现过模式串 t

  • 定义两个下标 j 指向模式串起始位置,i 指向文本串起始位置;
  • j 初始值依然为 -1
  • 接下来就是 s[i]t[j + 1] (因为 j-1 开始的)进行比较:
    • 如果 s[i]t[j + 1] 不相同,j 就要从 next 数组里寻找下一个匹配的位置;
    • 如果 s[i]t[j + 1] 相同,那么 ij 同时向后移动。
  • 如果 j 指向了模式串 t 的末尾,那么就说明模式串 t 完全匹配文本串 s 里的某个子串了。
int strStr(string haystack, string needle) {
	if (needle.size() == 0) {
	    return 0;
	}
	int next[needle.size()];
	getNext(next, needle);
	int j = -1; // // 因为next数组里记录的起始位置为-1
	for (int i = 0; i < haystack.size(); i++) { // 注意i就从0开始
	    while(j >= 0 && haystack[i] != needle[j + 1]) { // 不匹配
	        j = next[j]; // j 寻找之前匹配的位置
	    }
	    if (haystack[i] == needle[j + 1]) { // 匹配,j和i同时向后移动
	        j++; // i的增加在for循环里
	    }
	    if (j == (needle.size() - 1) ) { // 文本串s里出现了模式串t
	        return (i - needle.size() + 1);
	    }
	}
	return -1;
}

匹配过程如下:
一文搞懂KMP算法!!!

时间复杂度: O ( n + m ) O(n + m) O(n+m)
空间复杂度: O ( m ) O(m) O(m), 只需要保存字符串 needle 的前缀表。

放弃一件事很容易,每天能坚持一件事一定很酷,一起每日一题吧!
关注我LeetCode主页 / CSDN—力扣专栏,每日更新!

注:仅供学习参考,如有不足,欢迎指正!文章来源地址https://www.toymoban.com/news/detail-471808.html

到了这里,关于一文搞懂KMP算法!!!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 一文搞懂全连接算法和它的作用

    一文搞懂全连接算法和它的作用

    如果你是搞AI算法的同学,相信你在很多地方都见过全连接层。 无论是处理图片的卷积神经网络(CNN),还是处理文本的自然语言处理(NLP)网络,在网络的结尾做分类的时候,总是会出现一个全连接层。 那么到底什么是全连接层,这一层在神经网络中有什么作用,以及它和

    2024年02月20日
    浏览(7)
  • 一文搞懂分库分表算法,通俗易懂(基因法、一致性 hash、时间维度)

    一文搞懂分库分表算法,通俗易懂(基因法、一致性 hash、时间维度)

    最近手上一个系统的访问速度有点慢,老早前用多线程优化过一些接口,将一些复杂 sql 改成单表查询,走内存处理,成功的将 一些 10 多秒的接口优化到 500 ms,但是数据量上来了单表查询效率也有点慢了,不得不考虑进行分库分表了,当然我这里只进行分表,没分库,问就是

    2024年02月03日
    浏览(6)
  • 一文搞懂MD5、SHA-1、SHA-2、SHA-3,哪个算法比较安全

    一文搞懂MD5、SHA-1、SHA-2、SHA-3,哪个算法比较安全

    MD5、SHA-1、SHA-2、SHA-3都是比较常见的单向散列函数,这几种单向散列函数都有自己的特性。下面,给大家介绍一下它们的区别,以及MD5、SHA-1、SHA-2、SHA-3的安全性如何,哪种算法比较安全? 一、简介 单向散列函数是指对不同的输入值,通过单向散列函数进行计算,得到固定

    2024年02月15日
    浏览(15)
  • 《Towards Open Set Deep Networks》:一文搞懂开集识别算法 OpenMax:

    《Towards Open Set Deep Networks》:一文搞懂开集识别算法 OpenMax:

    《Towards Open Set Deep Networks》:https://github.com/abhijitbendale/OSDN 《Meta-Recognition: The Theory and Practice of Recognition Score Analysis》:https://github.com/Vastlab/libMR 说明:关于OpenMax算法的具体实现,有兴趣的可以备注来意q:3270348868 1. 激活向量 AV:即训练(测试)样本通过神经网络的倒数第二

    2024年01月20日
    浏览(12)
  • 一文搞懂Nginx(上)

    一文搞懂Nginx(上)

    是一个高性能的HTTP和反向代理web服务器,我们常用的功能有HTTP代理、负载均衡、动静分离、高可用集群,目前阶段我使用得比较多是就是代理和负载均衡,官方数据测试表明能够支持高达 50,000 个并发连接数的响应。占用的内存也特别的少。 优点: 1、负载均衡(可以减轻单

    2024年04月09日
    浏览(7)
  • 一文搞懂containerd

    一文搞懂containerd

    在学习 Containerd 之前我们有必要对 Docker 的发展历史做一个简单的回顾,因为这里面牵涉到的组件实战是有点多,有很多我们会经常听到,但是不清楚这些组件到底是干什么用的,比如 libcontainer 、 runc 、 containerd 、 CRI 、 OCI 等等。 从 Docker 1.11 版本开始,Docker 容器运行就不

    2024年02月11日
    浏览(8)
  • 一文搞懂隐私计算

    一文搞懂隐私计算

    隐私计算(Privacy computing)是指在保证数据不对外泄露的前提下,由两个或多个参与方联合完成数据分析计算相关技术的统称。 隐私计算作为跨学科技术,以密码学为核心理论, 结合了大数据、人工智能、区块链等多领域知识。其这些技术路线中,以安全多方计算为代表的基

    2024年02月07日
    浏览(9)
  • 一文搞懂性能测试

    一文搞懂性能测试

    我们经常看到的性能测试概念,有人或称之为性能策略,或称之为性能方法,或称之为性能场景分类,大概可以看到性能测试、负载测试、压力测试、强度测试等一堆专有名词的解释。 针对这些概念,我不知道你看到的时候会不会像我的感觉一样:乱!一个小小的性能测试,

    2024年02月08日
    浏览(13)
  • 一文搞懂HBA卡

    一文搞懂HBA卡

    HBA卡是一个简称,准确叫法应该是:主机总线适配器(Host Bus Adapter,HBA),也叫做FC-HBA卡(俗称:光纤网卡)、iSCSI-HBA卡(RJ45接口)。这是一个在服务器和存储装置间提供输入/输出(I/O)处理和物理连接的电路板或集成电路适配器。由于传输协议的不同而出现,一般用在服务器的

    2024年02月04日
    浏览(7)
  • [MySQL事务一文搞懂]

    事务(Transaction),顾名思义就是要做的或所做的事情,数据库事务指的则是作为单个逻辑工作单元执行的一系列操作(SQL语句)。 这些操作要么全部执行,要么全部不执行。 把一系列sql放入一个事务中有两个目的: 为数据库操作提供了一个从失败中恢复到正常状态的方法,同

    2024年02月05日
    浏览(9)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包