KMP算法是由一个问题而引发的:对于一个字符串 str (长度为N)和另一个字符串 match (长度为M),默认N≥M。如果
match 是 str 的子串,请返回其在 str 第一次出现时的首字母下标,若 match 不是 str 的子串则返回 -1 。
子序列:可以连续,也可以不连续,比如ac1de,abc123
子串/子数组:必然连续
二者有时候是混用的!
getIndexOf 方法:
即getIndexOf (str1,str2)返回一个整型
若match 是 str 的子串,返回其在 str 第一次出现时的首字母下标;
如果不是,则返回-1
最简单的方法是将 str 从头开始遍历并与 match 逐次比较,若碰到了不匹配字母则终止此次遍历转而从 str 的
第二个字符开始遍历并与 match 逐次比较,直到某一次的遍历每个字符都与 match 匹配否则返回 -1 。
易知此种做法的时间复杂度为 O(N*M) 。
KMP算法则给出求解该问题时间复杂度控制在 O(N) 的解法
原理:让前面配过的指导后面。
举例说明:
对于这样一个字符串
前缀取1,后缀取1,两者不等。
前缀取2.后缀取2,两者不等。
前缀取3.后缀取3,两者相等。
前缀取4后缀取4,两者不等。
前缀取5后缀取5,两者不等。
前缀取6后缀取6,两者相等。
但是!
不能要这一种情况!
所以d位置上的 最长前缀和最长后缀的匹配长度为3
再举一个例子:
求b前面的最长前缀和最长后缀的匹配长度
注意长度不能取5!
前缀不能取最后一个数,后缀 不能取到最前面的数
长度为4是最长的,所以b位置上的最长前缀和最长后缀的匹配长度为4
假设str2字符
我们求其中每一个数的 最长前缀和最长后缀的匹配长度
并且将值 返回一个数组
表示 每一个位置上 前面字符串的 最长前缀和最长后缀的匹配长度
0位置在前面过程中,没有字符串,所以默认-1;
1位置,即b,前面只有一个字符,我们强调过,前缀不能取最后一个数,后缀 不能取到最前面的数,人为规定 为0
2位置,即a,前面有两个字符,若这两个字符,相等,则为1;不等则为0!
最后结果:
假设两字符串一路都相等,直到x y
这时我们得到 y位置的 最长前缀和最长后缀(存放于next数组)
举个例子:
之前 算法。,t若与a不能匹配,则 :
接下来比较这两者是否相等!
清晰一点的图如下:
another 例子:
解释完过程,我们来看为何这么做,即这么做的实质:
在举个例子:
连续配两次
此时,以及没有办法再推了
如果最长前、后缀都没了,那么两个要统一换!
即 str1的下一个字符与str2 的0位置 互换!
往后推的含义:
乙指针指向 最长前缀和最长后缀的匹配长度所在的位置
我们以这个a位置和str1的甲位置开始匹配!
我们认为从i位置到j位置一律配不出str2。这是这件事情的实质!
Y之前 最长前、后缀字符串的 长度为:
将其放入next数组。
之前 讲到,推的实质是,j位置上的数,和0位置的数开始比较,只是因为前面一样,所以才从 此处开始 比较
我们认为,i位置和j位置之间,任意某个位置k,从k位置出发,是配不出整个str2的
为了证明上句话,我们可以假设可以配出
而这三者是一样的!
主方法代码:
接下来看getNextArray函数:
假设i位置之前 已经求解了所有next数组的值,如何求i位置上的呢?
假设i-1位置上的数,返回值为4,为了求i位置上的,我们就看 长度为4位置上的 下一个字符 和 i位置前面的字符,比较两个数是否相同
若相同,则i位置上的数,在i-1的基础上加1.
若不同:
此时,i-1的长度为5,比较这俩是否相同
若这时对上了,则n位置的长度为 cn位置上数+1 !
举例:
此时,t≠c;则将c的最长前缀和最长后缀分为两坨,然后 取其 最长前缀的后一个数和t比较!
a≠t,a不能继续往前分两坨了,所以k的最长前缀和最长后缀的匹配长度为0
若t变为a
因为c 的前缀长度为2,所以k就为3!
分析:最长确实是 aba,aba
代码分析:
cn是指 要跳到的位置!
进阶1 刚开始