408-数据结构-串匹配KMP算法

KMP算法

KMP算法也是串匹配算法,是从朴素模式匹配算法优化来的。
最主要的算法思想是:主串中匹配过的地方就不需要再进行匹配
朴素模式匹配算法主要就是暴力进行匹配,如果主串指针与模式串指针不相符,主串指针回溯至主串的起始匹配点的下一个,模式串指针回溯至头,再进行匹配。
而KMP算法只需要实现模式串指针回溯,而不需要将主串指针回溯,从而提高算法效率。

主串指针不需要回溯原因如下:
以’ABACDEG’匹配’ABAE’为例,在进行以第一个’A’作为起始点进行匹配的时候,匹配到’C’的时候会发现不匹配,如果按照朴素模式匹配就会以B作为起始点重新进行匹配。
但是,由于是到’C’发现不匹配,此时计算机就会知道在不匹配这个点的前面部分串为’ABA’,因为匹配成功呗。但是计算机不会知道’C’这个位置是’C’只是知道这个位置一定不是’E’。
那么,就不需要完全进行回溯比较,因为计算机已经可以知道前面是’ABA’,只需要将错误点与模式串中的’B’比较即可,因为前面是’A’呗。即只要修改模式串指针再进行比较即可,这就做到了不用将主串指针进行回溯,只需要修改模式串指针。
408-数据结构-串匹配KMP算法_第1张图片
408-数据结构-串匹配KMP算法_第2张图片

这说明出错点的位置与修改模式串指针位置有了某种关系,至于模式串指针需要修改至哪一个,其实需要取决于模式串的具体内容。KMP算法通常利用next数组解决这种映射关系。
模式串指针跳转位置=next[出错位置]
408只需要会手算next数组就行。具体方法:

  1. 以出错点左边划分一条线。
  2. 线左边匹配成功,说明主串肯定与模式串相等。
  3. 将模式串不断向右移一个单位,直到主串线左边的元素与模式串线左边元素相同或者整个模式串都移到了线右边为止,线右边的串位数即为需要跳转的模式指针的值。
  4. 出错位置的个数肯定与模式串串长相同,全部出错位置验算完毕也就求完了next数组。

next数组特殊性:对任意模式串,next[1]为0,next[2]为1.
因为第一个出错了肯定就需要将主串++,至于为什么跳转0,是因为在匹配成功时候,主串跟模式串指针都需要++,这俩可以合并一起成为一个判断条件。
第二个错了,肯定向右移一个,由于此时模式串本来就才匹配到第二个,线右边肯定是串的第一个,所以肯定跳转到第一个。

所以KMP算法逻辑变成:
主串跟模式串进行一一匹配,如果匹配成功,两个指针都++,如果匹配失败此时模式串指针即为出错位置吧,进行next数组继续映射,再进行匹配即可。

next数组优化

在匹配失败时候,计算机无法确定主串在该点字符是啥,但是可以知道它一定跟模式串当前的值不相同。所以如果错误位置在next映射值在模式串中的字符值与当前出错点的模式串的字符值相同,那么如果跳转之后再判断,一定不会匹配成功,所以直接将错误点在next数组的映射值改为原映射值在next数组的映射值即可。优化后的next数组称为nextVal。例如图片可以直接将next[3]映射值改为next[1]映射值0
408-数据结构-串匹配KMP算法_第3张图片

求nextVal数组:

  1. 求next
  2. 优化

你可能感兴趣的:(408-数据结构,算法,数据结构,c++)