由标题可知这篇文章主要讲解KMP算法。希望对想了解KMP算法的小伙伴有所帮助。
我们先要了解KMP算法的大致过程 (这是我在学习过程中认为比较好的视频)
(大致了解KMP算法过程的小伙伴也看看 也许会有所收获)
KMP算法和BF算法都是一个个字符进行判断 只是KMP算法在遇到不匹配字符时主串不需要回溯。
看完视频后我们需要了解这些东西:
1 模式串=子串:要进行判断的字符串 就是视频中的子串
2 前缀:不包含最后一个字符(要包含第一个字符)
3 后缀:不包含最前面的字符(同上,包含最后一个字符)
4 最大相等前后缀(核心):即到达某字符(包括这个字符)前缀和后缀拥有的 “相同的” “最大数量的"字符
5 next数组(第一个元素为0):用于存放最大相等前后缀数量
这篇文章的next【0】是等于0的版本
有两个版本,一种是next[0]=-1;
根据我的学习经历,对于刚学习KMP算法的小伙伴应该会有以下问题:
1 字符串判断时,不知道为什么可以这样跳过一部分字符
2 不知道next数组怎么计算
接下来我会按顺序一一讲解
问题1 不理解第一个问题的小伙伴大概率是没理解好最大相等前后缀的作用
重要信息--> 前面字符都匹配 当遇到不匹配的字符
我们就应该移动子串再进行比较。那怎么移动呢?
参考动图 可知我们应该去查找next数组前一个字符的对应的数字(也就是子串要移动到的下标)。这样移动的原因是:我们已经知道了之前的字符都匹配,只有当前的字符不匹配 我们只需要将当前字符移动到前一个字符的最大前缀下标(对应的next数组)后,使前一个字符字符的前缀的后缀重合,再继续匹配即可,如果还不匹配,那就继续查找前一个字符的next数组,当遇到next数组为0时,匹配还不成功,就把主串前移一位。
问题2:next数组怎么计算(以代码的方式)
首先,我们设置两个变量int i int j(i代表前缀,j代表后缀),分别代表当前所查找的字符最大前后缀位置。我们再设第一个字符对应的next数组值为0 (因为没有前后缀,就一个字符)一开始i为第一个字符的下标位置,j在i后面
i代表了最大前缀的长度,也是next数组的值
代表了当前匹配的字符,可以用来判断循环是否可以停止
循环条件我们就设置成当j大于模式串长度时,退出循环即可
接下来 我们对i和j(第一个字符和第二个字符)进行比较,看看是否匹配,若匹配,则将其填入next数组中,其值就是i的值,同时i和j同时加一,如果有匹配了,这两个变量再加一(表示此时最大相等前后缀长度为2)。若遇到不匹配的情况,我们就将i等于i的当前字符的前一个字符的next数组的值,和第一个问题原理相同。
当j等于模式串长度时,退出循环。