在KMP算法中有个数组,叫做前缀数组,也有的叫next数组。

每一个子串有一个固定的next数组,它记录着字符串匹配过程中失配情况下可以向前多跳几个字符。

当然它描述的也是子串的对称程度,程度越高,值越大,当然之前可能出现再匹配的机会就更大。

这个next数组的求法是KMP算法的关键,但不是很好理解。这个篇文章仅贡献给不喜欢看数学公式又想理解KMP算法的同学。

1、用一个例子来解释,下面是一个子串的next数组的值,可以看到这个子串的对称程度很高,所以next值都比较大。

位置i

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

前缀next[i]

0

0

0

0

1

2

3

1

2

3

4

5

6

7

4

0

子串

a

g

c

t

a

g

c

a

g

c

t

a

g

c

t

g

申明一下:下面说的对称不是中心对称,而是中心字符块对称,比如不是abccba,而是abcabc这种对称。

(1)逐个查找对称串

这个很简单,我们只要循环遍历这个子串,分别看前1个字符,前2个字符,3个... i个 最后到15个。

第1个a无对称,所以对称程度0

前两个ag无对称,所以也是0

依次类推前面0-4都一样是0

前5个agcta,可以看到这个串有一个a相等,所以对称程度为1前6个agctag,看得到ag和ag对成,对称程度为2

这里要注意了,想是这样想,编程怎么实现呢?

只要按照下面的规则:

a、当前面字符的前一个字符的对称程度为0的时候,只要将当前字符与子串第一个字符进行比较。这个很好理解,前面都是0,说明都不对称了,如果多加了一个字符,要对称的话最多是当前的和第一个对称。比如agcta这个里面t的是0,那么后面的a的对称程度只需要看它是不是等于第一个字符a了。

b、按照这个推理,我们就可以总结一个规律,不仅前面是0,如果前面一个字符的next值是1,那么我们就把当前字符与子串第二个字符进行比较,因为前面的是1,说明前面的字符已经和第一个相等了,如果这个又与第二个相等了,说明对称程度就是2了。有两个字符对称了。比如上面agctag,倒数第二个a的next是1,说明它和第一个a对称了,接着我们就把最后一个g与第二个g比较,又相等,自然对称成都就累加了,就是2了。

c、按照上面的推理,如果一直相等,就一直累加,可以一直推啊,推到这里应该一点难度都没有吧,如果你觉得有难度说明我写的太失败了。

当然不可能会那么顺利让我们一直对称下去,如果遇到下一个不相等了,那么说明不能继承前面的对称性了,这种情况只能说明没有那么多对称了,但是不能说明一点对称性都没有,所以遇到这种情况就要重新来考虑,这个也是难点所在。

(2)回头来找对称性

这里已经不能继承前面了,但是还是找对称成都嘛,最愚蠢的做法大不了写一个子函数,查找这个字符串的最大对称程度,怎么写方法很多吧,比如查找出所有的当前字符串,然后向前走,看是否一直相等,最后走到子串开头,当然这个是最蠢的,我们一般看到的KMP都是优化过的,因为这个串是有规律的。

在这里依然用上面表中一段来举个例子:

位置i=0到14如下,我加的括号只是用来说明问题:

(a g c t a g c )( a g c t a g c) t

我们可以看到这段,最后这个t之前的对称程度分别是:1,2,3,4,5,6,7,倒数第二个c往前看有7个字符对称,所以对称为7。但是到最后这个t就没有继承前面的对称程度next值,所以这个t的对称性就要重新来求。

这里首要要申明几个事实

1、t 如果要存在对称性,那么对称程度肯定比前面这个c 的对称程度小,所以要找个更小的对称,这个不用解释了吧,如果大那么t就继承前面的对称性了。

2、要找更小的对称,必然在对称内部还存在子对称,而且这个t必须紧接着在子对称之后。

如下图说明。

从上面的理论我们就能得到下面的前缀next数组的求解算法。

;
    ; )              
            ;
        ;       //如果遍历了所有子对称都无效,说明这个新字符不具有对称性,清0
    }
}

通过这个说明,估计能够理解KMP的next求法原理了。

 

KMP算法 --- 深入理解next数组的更多相关文章

  1. KMP 算法中的 next 数组

    KMP 算法中对 next 数组的理解 next 数组的意义 此处 next[j] = k:则有 k 前面的浅蓝色区域和 j 前面的浅蓝色区域相同: next[j] 表示当位置 j 的字符串与主串不匹 ...

  2. 自己对kmp算法的理解,借由 28. 实现 strStr() 为例

    做题思路 or 感想 : 就借由这道题来理解一下kmp算法吧 kmp算法的操作过程我觉得有句话很合适 :KMP 算法永不回退 目标字符串 的指针 i,不走回头路(不会重复扫描 目标字符串),而是借助 ...

  3. 对KMP算法通过代码生成next数组理解

    本文是根据考研数据结构2019版天勤高分笔记理解编写的: 首先给出代码: 1 void getnext(Str substr,int next[]){ 2 int i=0,j=0; 3 next[1] ...

  4. 字符串模式匹配之KMP算法图解与 next 数组原理和实现方案

    之前说到,朴素的匹配,每趟比较,都要回溯主串的指针,费事.则 KMP 就是对朴素匹配的一种改进.正好复习一下. KMP 算法其改进思想在于: 每当一趟匹配过程中出现字符比较不相等时,不需要回溯主串的 ...

  5. KMP算法的理解

    ---恢复内容开始--- 在看数据结构的串的讲解的时候,讲到了KMP算法——一个经典的字符串匹配的算法,具体背景自行百度之,是一个很牛的图灵奖得主和他的学生提出的. 一开始看算法的时候很困惑,但是算法 ...

  6. (收藏)KMP算法的前缀next数组最通俗的解释

    我们在一个母字符串中查找一个子字符串有很多方法.KMP是一种最常见的改进算法,它可以在匹配过程中失配的情况下,有效地多往后面跳几个字符,加快匹配速度. 当然我们可以看到这个算法针对的是子串有对称属性, ...

  7. 关于《数据结构》课本KMP算法的理解

    数据结构课上讲的KMP算法和我在ACM中学习的KMP算法是有区别的,这里我对课本上的KMP算法给出我的一些想法. 原理和之前的KMP是一样的https://www.cnblogs.com/wkfvaw ...

  8. 关于KMP算法的理解

    上次因为haipz组织的比赛中有道题必须用到KMP算法,因此赛后便了解了下它,在仔细拜读了孤~影神牛的文章之后有种茅塞顿开的感觉,再次ORZ. 附上链接http://www.cnblogs.com/y ...

  9. KMP算法中求next数组的实质

    在串匹配模式中,KMP算法较蛮力法是高效的算法,我觉得其中最重要的一点就是求next数组: 看了很多资料才弄明白求next数组是怎么求的,我发现我的忘性真的比记性大很多,每次看到KMP算法求next数 ...

随机推荐

  1. nginx location 的配置

    一.基本语法:location [=|~|~*|^~] /uri/ { … } 二.分类: 1.基本location:以“ = ”或“ ^~ ”为前缀或者没有任何前缀的 /uri/ 2.正则locat ...

  2. Android开发:第四日番外——Assets文件夹和RAW文件夹区别

    话说上回说到SQLite数据库,其中涉及到把已经设计好的数据库打包到APK中,提到可以放置在Assert文件夹或者RAW文件夹中,那么两者到底有什么区别呢?让我们来探究一下. 一.res/raw和as ...

  3. pip install使用豆瓣源

    这个是老问题了 pip install -i https://pypi.douban.com/simple/ selenium 类似的,npm和gem安装的时候可以使用淘宝源.

  4. mssql2012以后新增的offset分页,看起来爽死了!!!

              有没有办法让那时间显示精确到毫秒级呢!!!         2016年12月01日更新 正式用到项目中的时候才发现大坑,那个排序字段必须形成唯一 ,要不然就分页失败的        ...

  5. schedule() 和 scheduleAtFixedRate() 区别

    1.  schedule() ,2个参数方法:在执行任务时,如果指定的计划执行时间scheduledExecutionTime <= systemCurrentTime,则task会被立即执行. ...

  6. django shell 集合

    1.创建project $ django-admin startproject mysite 2.真正执行,修改数据库 $ python manage.py migrate 3.运行服务 $ pyth ...

  7. 再说 c++11 内存模型

    可见性与乱序 在说到内存模型相关的东西时,我们常常会说到两个名词:乱序与可见性,且两者经常交错着使用,容易给人错觉仿佛是两个不同的东西,其实不是这样,他们只是从不同的角度来描述一个事情,本质是相同的. ...

  8. 如何复制DataRow(dataTabel中的行)

    由于需要对dataTabel中的行进行上移和下移操作: row 1      行号0 row2       行号1 row3       行号2 例如将row3上移一行,即row2和row3对调位置. ...

  9. [转]make: 警告:检测到时钟错误。您的创建可能是不完整的。

    转自http://blog.csdn.net/maopig/article/details/6599660 我在make的时候也出现了同样的问题,不过不是什么大问题,这个不影响编译结果 分析原因可能是 ...

  10. SPI总线通信电路设计

    数据带宽=(总线频率×数据位宽)÷8 B表示带宽,F表示存储器时钟频率,D表示存储器数据总线位数,则带宽为: B(峰值带宽)=F(时钟频率MHz)×D(总线位数bit)/8 例如,PC-100的SDR ...