【数据结构与算法】KMP算法

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

前言

 在C语言的strstr的实现过程中,所涉及的算法较为简单,或者说只是一个简单的思路而已,在字符串过长时,所涉及的算法复杂度过大,那有没有比较简单的算法呢?这里就涉及到了KMP——由三位大佬提出的,下面我们一起来了解吧!

一 .KMP的来历

 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。
巨佬1:D.E.Knuth
巨佬2:J.H.Morris
巨佬3:V.R.Pratt
图片:
kmp算法,算法,算法,排序算法
简介:
 沃恩·普拉特(Vaughan Pratt) (出生于1944年4月12日)是 名誉教授 在 斯坦福大学 ,他是 计算机科学 。自1969年以来,普拉特(Pratt)对基础领域做出了一些贡献,例如 搜索算法, 排序算法 , 和 素性测试 。最近,他的研究重点是对 并发系统 和 楚空间.百科全书 site:ewikizh.top

我浅浅地膜拜一下,因为从0到1创造出一个算法,那真是太牛了!
说明:在看这篇文章之前我推荐先看一下B站的视频(选择适合你的!):
1.最浅显易懂的 KMP 算法讲解
2.KMP算法易懂版
3.有两个部分
第一:帮你把KMP算法学个通透!(理论篇)
第二:帮你把KMP算法学个通透!(求next数组代码篇)
在此基础上看这篇文章,可能收获会更大!

二.KMP解决的问题

1.引入

kmp算法,算法,算法,排序算法
 由于暴力求解(l两层for循环)的算法时间复杂度为:o(mn),我们大概看一下下面的图表:
kmp算法,算法,算法,排序算法
将m
n最大化可以看成n^2,可知:字符串越长,求出结果所需时间也就越大,有更好的办法吗?sure!巨佬们,创造出了KMP算法,解决了这个问题。

2.定义的引入

1.字符串前缀

简单理解:
1.从开头字母到倒数第二个字母
2.开头字母依次接上第一个字母,第二字母……到倒数第二个字母,就像火车一样。
例:abc
前缀:a,ab

2.字符串后缀

简单理解:
1.从倒数第一个字母到正数第二个字母
2.从倒数第一个字母开始,依次接上倒数第二个字母,倒数第三个字母……正数第二个字母,这里字母要倒着接。
例:abc
后缀:c, bc
说明:a这是首字母也是末字母,不是前缀,也不是后缀。

3.最长相等前后缀

例1:aba
前缀:a,ab
后缀:a, ba
最长相等前后缀:a,最长相等前后缀长度是1
例2:aaaa
前缀:a,aa, aaa
后缀:a , aa, aaa
最长相等前后缀:aaa,最长相等前后缀长度是3
例3:a
前缀:无
后缀:无
最长相等前后缀:无,最长相等前后缀长度是0

3.核心思想

kmp算法,算法,算法,排序算法
kmp算法,算法,算法,排序算法
kmp算法,算法,算法,排序算法
kmp算法,算法,算法,排序算法
kmp算法,算法,算法,排序算法

说明:我采用的是代码转换的思想,以及数学的换元法进行辅助理解。

三.next/prefix

1.next的含义

定义

 next是数组存放的是当发生比匹配的情况时:要进行的下一步操作,往往是当模式串的字符与对应的主串字符不匹配时,对应的下一步,不匹配的前一个字符跳到next下标对应的值或相似的运算。
 简单来说就是,下一步的该咋办,要写入next数组.

规律

一般是模式串下标和最长前缀后缀字符串的长度。
执行时间:当模式串的字符与主串字符串的对应字符不同时执行。
举例:
kmp算法,算法,算法,排序算法

注意:
这里就充分利用了上一次比较的结果,使用上次比较的结果,进行下一步的比较。这里就方便了许多.
为什么方便呢?
换元思想就是最大前缀后缀的核心, 也就是方便的原因,这里求出的最大前缀后缀长度,刚好与下标的计算差1,也就是跳去的下标,刚好与主串的前一次不一样的字符对应,可以接着比较。这里就比较凑巧。

2.next的求取

说明:
人脑计算和机器计算不一样,人脑是把字符串依次拿出来比较,计算机可做不到这样,只能将下一步可能的操作全部记录下来,也就是next数组。
那如何进行快速计算呢?
这里的主要思想:回溯思想
说明:回溯思想,就跟游击战的意思差不多,打的过就打,打不过就走。

1.准备工作

图解:
kmp算法,算法,算法,排序算法
框架:

void get_next(char arr1[], int next[], int len)
{
	next[0] = 0;//第一个字符为0,不管字符串的长度多大。
	int i = 0;//最开始的下标
	int j = 1;//最开始的字符串大于1的模式串的下标
	for (j = 1; j > len; j++)
	{
		while (arr1[i]!=arr1[j]&&i>0)
		{
			i = arr1[i - 1];
		}
		if (arr1[i] == arr1[j])
		{
			i++;
		}
		next[j] = i;
	}
}

2.思路和图解

kmp算法,算法,算法,排序算法

4.应用

1.字符串中找模式串,以及类似的问题。(strstr这个函数就是找模式串的函数)文章来源地址https://www.toymoban.com/news/detail-843443.html

  • 贴一份KMP的模版
vector<int> kmp(string& text,string& pattern)
{
    //求next数组
    int tsz = text.size(),psz = pattern.size();
    vector<int> next(psz);
    int index = 0;
    for(int i = 1; i < psz; i++)
    {
        char ch = pattern[i];
        while(index && ch != pattern[index])
        {
            //进行回退找最长匹配串与之匹配
            index = next[index-1];
        }
        if(ch == pattern[index])
            index++;
        next[i] = index;
    }
    vector<int> ans;
    //求子串的起始位置。
    index = 0;
    for(int i = 0; i < tsz; i++)
    {
        char ch = text[i];
        while(index && ch != pattern[index])
        {
            index = next[index-1];
        }
        if(ch == pattern[index])
            index++;
        
        if(index == psz)
        {
            //说明找到子串了,记录下标并进行回退
            ans.push_back(i + 1 - psz);
            index = next[index - 1];
        }
    }
    return ans;
};
  • 练习题:
  1. 3008. 找出数组中的美丽下标 II
  • 说明:KMP是一个很不错的算法,能将字符串匹配缩短到线性O(m + n),关键就在于,将前缀的信息记录,匹配失败时可快速找到下一个可能匹配的字符子串。

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

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

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

相关文章

  • 【数据结构】朴素模式匹配 & KMP算法

    🌈 自在飞花轻似梦,无边丝雨细如愁 🌈   🌟 正式开始学习数据结构啦~此专栏作为学习过程中的记录 🌟 子串的定位操作通常称为串的模式匹配,它求的是模式串在主串中的位置,而朴素模式匹配就是一种不断移动主串指针,每一次都和模式串依次进行比较的暴力求解方法

    2024年02月16日
    浏览(34)
  • 数据结构--字符串的KMP算法

    朴素模式匹配算法: 一旦发现当前这个子串中某个字符不匹配,就只能转而匹配下一个子串(从头开始) 但我们可以知道: 不匹配的字符之前,一定是和模式串一致的 color{red}不匹配的字符之前,一定是和模式串一致的 不匹配的字符之前,一定是和模式串一致的 我们可以利用

    2024年02月12日
    浏览(50)
  • 数据结构—串的详细解释(含KMP算法)

    1.1串的定义 串:串是由零个或多个字符组成的有限序列,又叫字符串(其的存储结构包含顺序表存储、单链表存储的形式。) 一般记为s=\\\"a1a2a3....an\\\"(n=0),其中,s是串的名称,用双引号(也可以使用单引号)括起来的字符序列是串的值,注意引号不是串的内容。ai(i=i=n)可以是字母、

    2023年04月09日
    浏览(32)
  • 【夜深人静学数据结构与算法 | 第一篇】KMP算法

    目录  前言:  KMP算法简介: 引入概念: 前缀后缀 前缀表: 简单例子: 暴力遍历: KMP算法:​  KMP算法难点: 总结: 本篇我们将详细的从理论层面介绍一下什么是KMP算法,相对应的力扣刷题专栏里也会有相对应的习题,欢迎各位前往阅读。           KMP算法是一种字符

    2024年02月08日
    浏览(57)
  • (C语言)数据结构算法-病毒感染检测(BF算法&&KMP算法)

    病毒感染检测: 医学研究者最近发现了某些新病毒,得知它们的DNA序列都是环状的。为了快速检测出患者是否感染了相应的病毒,研究者将患者的DNA和病毒的DNA均表示成一些字母组成的字符串序列,然后检测某种病毒DNA序列是否在患者的DNA序列中出现过,如果出现过,则此人

    2024年02月08日
    浏览(38)
  • 数据结构-串-KMP算法详解(Next数组计算)(简单易懂)

    本文章就专讲kmp,暴力匹配就不讲了(我相信能搜索kmp的,暴力匹配算法应该也都了解过了) 为什么网上那么多讲kmp 我还发文章,很多文章我觉得讲的不是太通俗易懂,大多数我看起来都觉得有些懵逼 提示:以下信息来源百度 KMP算法是一种改进的字符串匹配算法,由D.E.K

    2024年02月06日
    浏览(33)
  • 《数据结构》实验报告四:串的模式匹配(BF算法、KMP算法)

    1、了解 串 的基本概念。 2、掌握 串的模式匹配算法 的实现 。 说明以下概念 1、模式匹配:          串的模式匹配就是 子串的定位运算 。          设有两个字符串 S 和 T ,S为 主串(正文串) ,T为 子串(模式串) 。在主串S中查找与模式串T相匹配的子串,若匹配成功,确定

    2024年02月01日
    浏览(43)
  • 【数据结构】字符串匹配|BF算法|KMP算法|next数组的优化

    字符串匹配算法是在实际工程中经常遇到的问题,也是各大公司笔试面试的常考题目,本文主要介绍BF算法(最好想到的算法,也最好实现)和KMP算法(最经典的) BF算法,即暴力(Brute Force)算法,是普通的模式匹配算法,BF算法的思想就是将目标S的第一个字符与模式串T的第一

    2024年02月04日
    浏览(42)
  • 【数据结构】模式匹配之KMP算法与Bug日志—C/C++实现

    ​ 🌈 个人主页: Sarapines Programmer 🔥  系列专栏: 《数据结构奇遇记》 🔖墨香寄清辞: 墨痕寄壮志,星辰梦未满。 通幽径心凝意,剑指苍穹势如山。 目录 🌞1. 模式匹配的基本概念 🌞2. 模式匹配的解决办法 🎈2.1 暴力匹配(BF)算法 🎈2.2 KMP算法 🤖2.3 BUG记录_KMP算法 1

    2024年02月04日
    浏览(41)
  • C语言数据结构+KMP算法next数组优化计算方法+优化后子串匹配代码实现

    通过我之前那篇KMP算法的讲解,我们可以快速手算KMP算法的next数组,但是之前计算的next数组在一些情况下会有缺陷,比如模式串’aaaab’和主串’aaabaaaab’进行匹配 令模式串指针为j 当第一个元素不匹配时,下一次匹配还是要从模式串的第一个元素与主串匹配,其实我们可以直接写

    2024年02月06日
    浏览(34)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包