IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【串】KMP算法 -> 正文阅读

[数据结构与算法]【串】KMP算法

1.朴素算法

主要包含两个部分,打个比方:

主串:整个百度出来的结果

子串:我们输入的数据

image-20220406201547361

我们如何将我们子串的内容与我们主串的内容进行相互匹配呢?

我们来进行一个案例测试下:

S = “alibabaalimama”

T = “alimama”

我们进行模式匹配的时候,有一种方式叫做朴素匹配方式(BF)我们先用这种方式来进行匹配,但是这种匹配方式,效率不是很高,于是我们之后就引入了KMP算法的样例,在朴素匹配的基础上进行匹配:
在这里插入图片描述

朴素匹配算法核心,也是进行一步一步遍历所得到,他用的主要是两个for循环。如下代码:

for (i=0;i<m;i++)
    for(j=0;j<n;j++)

两个for循环,会在开始的位置,慢慢遍历,当我们第一次i=4,j=4的时候,出现了不相同,于是我们的外层循环j++,进入下一步循环。当我们i=2,j=1的时候,出现了不相同的串,于是我们继续执行外层循环的j++,然后依次迭代下去,直到最后,遍历到i=9,j=1的时候,我们循环全部的结果之后,发现,字符串,全部匹配,此时我们就返回结果。

以上的这种方式,比较暴力,进行的比较慢,主要核心思想就是当子串和主串不匹配的时候,子串往下移动一个.时间复杂度为O(n*m)。这种方式是比较鸡肋的。所以引入了我们下面的这种kmp算法的方式来计算,能够大大提高了效率。

缺点是:不太能够智能,每次都是一个一个的往后面移动,然后进行遍历对比,有些时候,我们匹配过的位置,是不需要重新迭代的,但是朴素算法,依旧会从头开始迭代。

我们发现,i和j标注的是它不匹配时候的位置,于是我们可以想象下,是否,下次我们可以从这个不匹配的位置开始执行呢,而不是从头开始。

2.kmp算法

kmp算法就是对应的朴素算法的一种改进方式:

核心思路就是求我们需要的next数组,而next数组针对的是子串而言的。

next数组,又分为几种情况;如下图所示

image-20220406203123665

我们找出子串

image-20220406203527171

通过给出的字符串,来计算他的next数组

image-20220406203623975

由于我们计算的单引号字符串,因此它的下标是从1开始的,我们开始对照公式来计算。当编号为1 的时候,对照公示,公式,他的next数组中对用的值为0。当编号为2时,我们把当前编号2后面的所有串都去除掉,此时我们只剩下一个a,对应的a是没有构成一个对称关系的 ,因此,在我们公式中,是属于其他情况,因此对应b的next数组值为1。此时我们遍历到编号为3的时候,我们将3与后面所有的串都删除,此时只保留了ab,ab仍旧是不存在对称关系的,于是我们对应编号3的他的next数组值也仍旧为1。

image-20220406204354459

当我们遍历到编号为4的时候,我们将编号4和之后的所有串都去除,此时只剩下“aba”,aba存在着一个对称关系。对于中间b,a成对称关系。此时我们的编号需要加1.那么对应的编号4他的next数组的值是2。

image-20220406204548964

当我们遍历到5编号是,将5和之后的所有元素都去除,然后此时只剩下”abab”,我们发现左边的ab与右侧的ab存在着某种对称关系,此时,我们计算next数组,那么对应的编号5的next数组值即为上一个元素值加1.即为3。

image-20220406204744489

当我们遍历到编号6的时候,将6个之后所有元素都去除,然后此时只剩下”ababa”,我们发现,左侧”aba”与右侧的”aba”存在着某种对称关系,因此在我们计算next数组的时候,发现是3个元素存在对称关系,因为我们的next数组值为4;

image-20220406204937331

当我们遍历到编号7的时候,将7编号之后的所有元素都去除,然后此时只剩下,”ababaa”此时我们发现,收尾两个”a“存在某种对称关系,将中间“baba“当做对称轴,此时存在一个a的对称关系,那么next数组的下标即为2.

在这里插入图片描述

当我们遍历到编号8的时候,将8编号之后所有的元素都去除,然后此时只剩下。”ababaaa”,我们发现此时和上述情况类似,因此,他的next数组值也为2

image-20220406205400208

当我们遍历到编号9的时候,将9之后所有元素都去除,然后此时只剩下,”ababaaab”此时我们发现首尾元素”ab”存在着某种对称关系。因此,我们对应的9编号的next数组值为3.此时我们已经全部计算出了,我们整个串的next数组。

image-20220406205556688

此时我们用另外一个串来验证我们的计算方式:用我们找某种对称关系的方式来进行求解next数组。从某个地方开始划线,切割之后看是否重合,想尽办法进行切割,找到最大重合(收尾重合)

image-20220406205734298

总结一下上面计算方式的口诀:

切两次:(相尽办法去切割,)

第一次:取前面的

第二次:(重新切)取后面的

如果两者重合,那么MAX就是字符数+1。

此时我们通过一个题目来计算验证下我们的方式:
在这里插入图片描述

依据刚刚方式,我们已经计算出了,子串的next数组,为[-1,0,0,1,1,2]

在kmp算法中,i是不会变小的。

我们进行实际匹配操作

image-20220406210246303

第一次失配的时候,i=5.j=5,对照着next数组计算之后,我们可以得到,i=5,j=2.那么我们主串下标为5的字符和子串下标为2的字符进行对照。如下图

image-20220406210535520

此时在位置i=8,j=5的时候,主串和子串再次失配,因此,对照着next数组,我们可以得到。i=8,j=2.将主串下标为8的字符,和子串下标为2 的字符进行位置匹配。

此时依次,计算,最终即可得到我们想要的结果。

总结:

KMP算法的核心是计算子串的next数组,然后通过计算的next数组,来进行位置匹配,通过计算的j的位置,去next数组中去寻找我们对应的位置,然后由于在next数组中。i是不会变小的。依次遍历。因此这样大幅度提高了,我们遍历的效率。它的时间复杂度为O()m+n)

可能以上描述太过于口语化,具体想了解如何计算的,可以私信我。

过计算的j的位置,去next数组中去寻找我们对应的位置,然后由于在next数组中。i是不会变小的。依次遍历。因此这样大幅度提高了,我们遍历的效率。它的时间复杂度为O()m+n)

可能以上描述太过于口语化,具体想了解如何计算的,可以私信我。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-07 22:56:50  更:2022-04-07 22:57:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:49:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码