kmp的思路总是断断续续的 有点菜 写一下看看能不能串一下思路让路线清晰一点
模式串p 匹配目标串 s
第一步: 求p的next数组
next数组是找出了p中所有长度里的前缀子串和位置对称的子串是否是完全相同的位置有哪些。
这中间还牵扯到一个小证明。也就是为什么比j更小的候选next[i]一定是next[next[j]]这问题比较好理解就不说了。
但是就要提问了:为什么要求p的next数组? 有什么用?
第二步:求s和p的匹配位置有哪些
在第二步里 :首先先确定匹配成功了,只要第一个字母对上眼了才有后续的故事。
也就是所谓的while(j && s[i] != p[j+1]) 中的判断条件的前半句,这也解释了为什么要用j=0开始 而后半句的判断为j+1
就是在于j的每次叠加都是一次判断 先判断j+1这个位置是否可以用,可以了再j++,不可以就回退。
j的物理意义就是匹配成功的次数,我们费了那么大劲让j从0开始而数组从1开始就是为了体现这个意义
j就意味着已经匹配的字符串的长度是多少 一开始是0,第一个字母对上眼了才开始不是0了。
下面就开始分类讨论了
::
如果一直对不上眼循环就一直空跑 一直跑完
如果对上了: 第一次就直接j++了。
如果不是第一次,是234567次的话,就要判断下一个位置是不是匹配的。也就是s[i] != p[j+1]还是s[i] == p[j+1],如果
是前者那么j =next[j]了。
这里就和第一个问题扯上了 为什么要求next数组然后在这里使用next数组呢
这里j回退了到了next[j],其实对于母串s而言,j也是回退到了next[j],因为已经匹配的部分肯定是相同的了,而next[j]的定义是什么来着,小于j的长度里面(因为等于j就没有前缀串和后缀串之分了 不符合定义)前缀串和对称的后缀的串的最长的长度是多少.前缀串就是p的前缀,因为j对于p来说意味着匹配的长度,而长度肯定是从前往后的,对吧。而对于s来说,匹配到的那个位置并没有动,至少我们没有去动它。因为不需要去动它,它作为后缀的部分被我们默认提取了之后再考虑后面的情况就可以了.
总结一下为什么一直在扯前缀和后缀,因为前缀就是模式串p的前面那部分,而后缀是已经匹配的部分s的后面那部分,
因为匹配的失败我们只能尽量提取还可以使用的部分,也就是next[j]这一部分 不用再去重新匹配了