KMP算法(代码+图解证明)

来源:互联网 发布:windows live影片制作 编辑:程序博客网 时间:2024/04/29 18:15

        KMP算法用于字符串匹配,是相较于朴素字符串匹配。所谓朴素字符串匹配就是从头到尾开始一个位置一个位置匹配,当前位置匹配失败则会从下一个位置开始继续匹配。

        KMP算法则是可以跳,能往前跳多远就往前跳多远。我们知道算法尽量要简化计算、去冗余、记忆搜索。KMP就是利用了去冗余的思想往前跳到某一位置继续匹配。而中间未匹配的丝毫不会有影响,这要归结于我们next数组的定义。

       所谓next数组中next[i]就是记录如果当前位置位置不匹配,字符串可以往前跳多远进行重新匹配。所以next[i]就是计算i之前字符串的最大回文长度(就是前缀和后缀相等的最大长度)。中间跳跃的点都是不用匹配的点,这个可以证明。


       如图,我们中间跳过的位置,如果存在有用的,即b'>b的长度。这种情况反证了我们b计算错误,也即我们next数组没求最长的,也就是没求对。故而,跳过的就是没用的。

       那么指导跳跃的next数组的求法如下图所示。


       上图演示的是next[i]这一位的计算方法,使用到了递归。这些说明白了,直接上代码。

#include<iostream>#include<string>using namespace std;int * getNextArray(string ms) {if (ms.length() == 1) {int *a=new int[1];a[0]=-1;return a;}int* next = new int[ms.length()];next[0] = -1;next[1] = 0;int pos = 2;int cn = 0;while (pos < ms.length()) {          //next数组从2之后大于等于0if (ms[pos - 1] == ms[cn]) {next[pos++] = ++cn;} else if (cn > 0) {cn = next[cn];} else {next[pos++] = 0;}}return next;}//s是原串,m是模式串 int getIndexOf(string s, string m) {if (s == "" || m == "" || m.length() < 1 || s.length() < m.length()) {return -1;}int si = 0;int mi = 0;int* next = getNextArray(m);while (si < s.length() && mi < m.length()) {if (s[si] == m[mi]) {si++;mi++;} else if (next[mi] == -1) {si++;   } else {mi = next[mi];}}return mi == m.length() ? si - mi : -1;}

      KMP算法其实不难,仔细研究下就可以理解了。


0 0
原创粉丝点击