1:首先我们要了解kmp算法是用来干什么的
2:接着我们要了解kmp算法与暴力法找字串的区别在哪里,为什么kmp算法可以实现高效
3:接着我们要了解next函数值代表的是什么
4:通过这三步的了解我们可以理解next如何来求next数组的值,当然在这里我们不用了解具体代码中next数组是如何被用来快速求相同字串的
一:kmp算法是用来干什么的
①:从书上我们可以了解到kmp算法是用来从主串中快速找出和模式串相同的字串的(具体有名词不理解可以去看书)
二:kmp算法与暴力法找子串的区别在哪里,为什么kmp算法可以实现高效
1:接们来先来思考这么一个问题在计算机中如何判断主串:ababcabcacbab中是否存在这样一个模式串(字串):abcac(数据结构算法4.5)
解题步骤:对于我们人来说判断是否存在只需要肉眼看一遍就行,但是机器却不能够识别。因此我们先需要有一个能够让机器看懂的语言去判断。
暴力求解:
①:我们先把两个字符串分别储存到两个数组当中
②:因为要找到是否具有这种字串 我们需要对两个数组中的字符一个个去做对比,我们先对比每个数组的第一个数组发现相等,那么我们需要对比每个数组的第二个元素,看是否相等。最好的情况是每次对比的元素都相同。但是如果在其中有元素不相同了,那么我们又要如何比较呢?
③:其实我们可以把这种比较分为二种类型:一种与字串中第一个元素比较就不相同了,第二种是在字串的第一个元素之后的元素比较才发现不同
假如我们上面的主串中第一个元素为b,那么我们比较的时候会发现主串和字串的第一个元素不相同了,那么我们就需要把主串中的第二个元素跟第一个元素先比较,如果还不同的话,我们需要让主串的第三个元素跟字串第一元素比较,依次类推........。
如果我们在字串的第一个元素之后才发现有元素不相同:比如说对比主串跟模式串,我们会发现第三个元素两者不相同,那么我们应该继续让子串的第一个元素跟第二个元素相比较。如果相同的话我们就要比较第三个元素(主串)跟第二个元素(字串).........
比较的两种不同情况的操作就按照上面所说的循环实现就行了。
从上面的描述中我们就可以知道当:在第一个元素之后的元素比较中发现了不同,那么我们又需要回到子串中的第一个元素与现在子串所对应的主串下一个元素相比较。(这个就是暴力求解的坏处所在)
主串:ababcabcacbab
模式串(字串):abcac
在这里可知道第三个元素不相同:如果让机器来比较的话又要让主串的第二个元素跟子串的第一个元素比较一次:但是如果让我们人来看的话很明显可以知道两者是不相同的,我们只需要从子串的第一个元素跟主串的第三个元素相比较就行了。那如何是我们写的代码拥有跟我们人眼一样的能力呢?(这就是kmp算法所要解决的问题,也是它时间效率高的原因,减小了比较次数)
kmp算法解决这个问题的关键就是在于:当它遇到不相同的字符时,它通过已知道的匹配相等的字符串中找,按照字符的排列顺序长度最大的字符串然后移动位置。
例如:
主串: ababcabcacbab
模式串(字串):abacac
这时候我们会发现第四个元素不同,那我们就需要重新寻找比较的起点:很简单因为我们的目的是要寻找有不有相同的字串,于是我们直接可以把字串移动到主串的第三个元素位置然后比较第四个就行了。
同时在书上我们可以知道我们只需要研究模式串就行了:这是因为我们可以根据模式串的匹配情况来确定移动的位置(这时候你的脑海里就要出现两个字符串,虽然都是模式串但是要注意他们元素分别对应的位置)
这里很抽象作者可能没有解释清楚,可以私信我。
为什么next数组的第一个值是0呢?
三:
通过教材的阅读我们可以知道next数组储存的是对应元素当出现不匹配的时候,主串元素需要和字串对应的位置的下标,也就是说是储存下标的。
这就可以解释为什么next数组的第一个值为0了,当第一个元素不匹配的时候我们需要把第一个元素与主串的第二个元素相对比了,那么如何实现这种移动呢就是把子串0下标的与主串1下标的相对齐就是了,这就是间接的让子串下标为1的与主串下标为2的对齐了就可以比较了。(注意这里的串用数组储存的时候下标为0的是储存字符串的长度的,因此开辟空间的时候需要对开辟一个)
本篇文章基于kmp算法中比较抽象的理解可能读起来雨里雾里的,有不懂的欢迎大家和我交流。