KMP算法详解

来源:互联网 发布:泗阳网络直通车 编辑:程序博客网 时间:2024/06/06 03:28

看了不少网上别人关于KMP算法的理解,大部分刚开始都看不懂,讲的都很晦涩,或者说他们把最核心的东西(我胡说的,他们都是大牛)给讲复杂了,不过我还是看到了一篇讲解的非常好的文章点击打开链接,这个人是从这个外国友人的文章里理解KMP的,点击打开链接,文章写的通俗易懂,不过这两个人的文章里似乎也没有讲明白KMP算法的精髓,我就斗胆说一下我自己对于KMP算法的理解。

BBC  ABCDAB  ABCDABCDABDE

        ABCDABD

我们把上边的串叫做父亲串,下边的串叫做儿子串。

依图中所示,儿子串匹配到父亲串的空格符号处时两个串不再匹配那么接下来我们就让儿子串右移一位,然后检验是否匹配。这是我们解决字符串匹配问题运用的最基础的解法,KMP算法其实就是最基础解法的优化,优化在哪儿了呢?所以说,KMP算法最核心的部分就是它优化在哪儿了?我接下来的内容都是致力于解释和解决这个问题,我希望你也能带着这个问题自始至终的看完我的这篇文章。

我接下来的这一段是最重要的部分。

我们还是以上边这个例子来看,儿子串右移一位之后变成这样:

BBC  ABCDAB  ABCDABCDABDE

          ABCDABD

KMP算法的核心思想就在这!我们发现儿子串右移一位之后是不匹配的!基础解法之所以时间复杂度高就高在这:得右移一位之后才能知道是不是匹配!!! 也就是说,基础解法的时间都浪费在了不断右移一位的过程中了,而这其中大部分右移一位之后的结果都是不匹配的,那么我们不仅会很生气,我辛辛苦苦右移一位之后竟然还不匹配!!!作为一个聪明人,我们要做的就是尽量不去做无用功,也就是那些右移一位之后仍然不匹配的右移操作。讲到这我想上面我提出的那个问题你已经能回答出来了。对,KMP算法就是帮助我们去判断我们接下来要进行的右移一位的操作有没有用的一种算法。如果接下来右移一位有用,那么我就右移一位,如果没用,那么我就右移两位,然后KMP算法再帮你判断右移两位有没有用,以此类推,知道发现右移N位有用时,才进行移位操作。 我这里用了我自己造的两个名词“有用”,“没用”,有必要解释一下,有用:右移N位之后不能确定儿子串和父亲串匹配不匹配,也就是右移N位之后,儿子串和父亲串可能匹配,也可能不匹配。无用:右移N位之后可以100%确定儿子串和父亲串不匹配。

上面一段我把最开始提出的那个问题给解决了,但你会问,KMP算法是怎么知道右移N位有没有用的呢?你的这个问题问的非常好,我想这个问题正是KMP算法发明者发现这个算法时第一个想到的问题。好,我们还是以上面的例子为例。

BBC  ABCDAB  ABCDABCDABD

          ABCDABD

通过KMP算法我们能知道这次的右移一位操作是无用的,具体他是怎么做到的呢?接下来我给出详细的解释。在父亲串的空格符号之前,儿子串和父亲串是匹配的,匹配的字符串为ABCDAB,长度为6。那么我现在右移一位,右移一位之后我要再次检验儿子串和父亲串是不是匹配,以上面这个例子为例,我要检验父亲串的BCDAB和儿子串的ABCDA是不是匹配。到这里就是整个KMP算法的来源了!!! 你发现了没有,此时父亲串的BCDAB不正是儿子串ABCDABD的一个字串嘛,我检验父亲串和儿子串是不是匹配,竟然就是检验儿子串和儿子串的字串是不是匹配!!!并且这个检验操作在整个模式匹配中要重复运行很多次,这个操作也正是字符串模式匹配耗时最多的地方!那么要想降低时间复杂度,我们就必须从这下手。这时,我们的研究对象就从父亲串和儿子串转到了仅仅只是儿子串性质的研究。好,那么我们就来看看儿子串有什么性质可以帮助解决这个问题。还是以上边这个例子为例。儿子串为:ABCDABD  上面我们说到:“我检验父亲串和儿子串是不是匹配,竟然就是检验儿子串和儿子串的字串是不是匹配!!!”,那么我们就来看看儿子串和儿子串的字串的匹配有那些技巧。

1:ABCDAB                                 tips: ABC

2:ABCDABD                                            CAB

我们假设上面tips的情况可以看作是匹配的。好,我来问你,2串向右右移几位才会出现1串和2串匹配的情况?四位吧。但这是你数出来的,太慢!我们能不能不数,直接算出右移几位后会匹配成功?答案是可以的。这就是所谓的KMP算法的next数组!这个next就是告诉我们向右右移几位是有用的!!!好了,讲到这应该就算讲解完毕了,我觉得我已经把KMP算法的核心思想说出来了,得喝口水放松一下了,哈哈哈。


0 0