分类: 数据结构

  • 数据结构-串-KMP算法详解(Next数组计算)(简单易懂)(垃圾文章多年后我也看不懂了)

    本文章就专讲kmp,暴力匹配就不讲了(我相信能搜索kmp的,暴力匹配算法应该也都了解过了)
    为什么网上那么多讲kmp 我还发文章,很多文章我觉得讲的不是太通俗易懂,大多数我看起来都觉得有些懵逼

    KMP介绍

    提示:以下信息来源百度

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

    上面讲了kmp需要求匹配字符串的next数组来快速匹配,那我们先来讲解一下如何求next数组


    一、求Next数组

    求Next数组前我们需要了解字符串的前缀表后缀表

    前后缀表

    如字符串“ABCD”的前后缀表

    在这里插入图片描述

    了解完字符串前后缀,接下来我们要开始求最长公共前后缀

    求最长公共前后缀

    我们以“aabaac”为例

    在这里插入图片描述

    字符串中要没有公共前后缀就为0

    从以上方法就能求出字符串“aabaac”的最长公共前后缀数组
    [0,1,0,1,2,0]

    最长相等前后缀表转Next数组

    当然变成Next数组前还需要进行简单的处理(其实也就把最长公共前后缀数组右移而已)
    在这里插入图片描述

    在最长公共前后缀前面加上 -1 并去掉最后一位就是next数组了
    Next数组的第一位永远是-1,第二位永远是0

    注意:Next数组有很多种求法,依据匹配字符串的代码来做选择,我选择的方法next数组第一位是-1,还有另一种方法开头是0,但原理都是相同的所以不必纠结


    二、使用Next数组来匹配字符串

    为了能较好体现kmp算法:
    主串:”aaacaacaaad
    模式串:”aaad
    模式串Next数组:[-1,0,1,2]

    在主串和匹配串字符相同的情况下,指针 i 和 j 后移

    或者遇到主串和匹配串字符不相同但next值为-1时指针 i 和 j 后移

    步骤一
    1i、1j、2i、2j代表指针位置及步骤,中间字符相等的地方我就不讲了,就主要讲重点的地方

    指针4i4j的字符不相同,不匹配位置的next值为2(蓝色的a),所以需要将匹配串右移到匹配串索引2的位置
    请添加图片描述
    步骤二
    匹配串后移后指针ij的字符依然还是不相同,不匹配位置的next值为1(蓝色的a),所以需要将匹配串右移到匹配串索引1的位置
    请添加图片描述
    步骤三
    匹配串后移后指针ij的字符依然还是不相同,不匹配位置的next值为0(蓝色的a),所以需要将匹配串右移到匹配串索引0的位置
    请添加图片描述
    步骤四
    匹配串后移后指针ij的字符依然还是不相同,但这时next值为-1,这就需要指针i和j向后移
    请添加图片描述
    步骤五
    指针i和j后移后,(中间字符相同的地方就不解说了),指针到3i和3j的字符不相同,next值为1,然后就和之前讲的步骤一样,需要将匹配串右移到匹配串索引1的位置
    请添加图片描述
    步骤六
    后面的步骤就不再多叙述,自己看图分析
    请添加图片描述
    步骤七
    请添加图片描述

    步骤八
    然后这就匹配完成了
    请添加图片描述


    总结

    代码后续会补充
    非常感谢您能看到这,本人第一次写文章,所以我可能讲的不是很好,如有问题望大家能多多提醒,感谢。下次讲sunday算法
    注:如看不懂,可以的话,麻烦您在评论区中发句看不懂,好让我知道我写的烂不烂