KMP算法
听完之后,你至能知道kmp算法的原理是什么样的。他是怎么做到比较的指针不需要回溯。并且听完之后你会求next的数组。到这里来应对一般校的kmp算法考题就足够了。这节课仅仅是初步理解,让你学完之后感觉眼前一亮。
什么是kmp算法?就是快速的从一个主串中找出你想要的子串。下面的串叫做模式串。Camp算法就是从主串中快速找到模式串。kmp算法强调一个快字,不快的话叫做幼稚模式串匹配算法。(幼稚模式串匹配算法也是最直观的,最容易想到的算法)
幼稚模式串匹配算法:
扫描到某个位置发现不匹配了
就让模式串整体后移一位。按这种方法来找,如果主串中含有模式串相同的字符,那么一定能找到。从上一步到这一步,指针有一个往回跑,也就是向左移动,重新指向a的动作。这个动作叫做回溯。回溯就是造成这个简单的算法效率比较低的主要原因。而km p算法可以做到仅仅后移模式串,比较指针不回溯。
kmp算法
回到刚才主串与模式串两个位置不匹配的状态。
这时候我们观察箭头左边的一部分上下是完全匹配的。同时模式串左右两边有两个子串是完全匹配的。这两个子串被称为模式串的公共前后缀。
下一步就是k mp算法的核心。直接移动整个模式串使公共前后缀的前缀移动到后缀的位置。这样移动可以保证当前比较指针左边的位置是上下一致的。
这里有一个疑问。一下把前缀匹配到后缀的位置,中间有没有可能跳过匹配的情况?答案是中间没有匹配的情况。你可以把上边的主串,也就是箭头左边公共的部分。当成箭头左边模式串的一个分身。他们中间公共的部分。要么是前缀的部分,要么是后缀的部分。其他位置摆放都不可能产生我们想要的匹配结果。
其实分析这个问题的时候,我们不需要看主串,因为主串的部分和下面模式串的部分是一样的。所以我们只看模式串的部分就能分析出来。当模式串中x的部分不匹配。这个时候我们只需要找到之前的一部分的公共前后缀。然后往前移动模式串,使得模式串中前缀的位置来到后缀的位置。就可以继续往下比较了。把模式串的信息研究透彻之后,用它就可以与任何的主串进行匹配了。
通过刚才的分析,我们知道我们不可能在前后缀的中间找到可以匹配的位置。如果有的话就说明模式串中有更长的前后缀。那么这一段才是我们要找的公共前后缀,这里我们要引出一个最长公共前后缀的概念。也就是说如果一个模式串中有多对公共前后缀,我们要取最长的那对。且长度要小于比较指针左端这个长度。
当我们在移动模式串的过程中,发现模式串的长度超过主串的长度,就可以判定为匹配失败。
一般字符串都存在数组中。数组存在内存中,内存是不可能移动的,所以这里只是一个形象化演示。
模式串
模式串可以从零开始存,也可以从一开始存。大部分学校采用从一开始存的方法。如果从零开始存原理是一样的,只不过相差了一
如果从第一个位置开始就不匹配,那么把模式串前一位。(让模式串中1号位的字符,与主串中下一个位置的字符相比较。)
如果2号位不匹配,发现箭头左边的子串长度只有一,因为公共前缀的长度要求小于这个子串的长度。那公共前后缀的长度只能是零了,那么这个模式串向后移动。(比较指针所指的位置。就是指针发生不匹配的位置。这种情况下要将模式串的1号位与主串的不匹配位置进行比较。)
如果3号位与主串发生不匹配,指针前面的字符为ab,最长公共前后缀长度为零。情况与二号位一致
当前公共前后缀的长度为三,那么我们将从4号位开始匹配。如果公共前后缀长度为n,那么就得到n加一位于主串当前位进行比较。