KMP算法

看这个视频就好啦

https://www.youtube.com/watch?v=dgPabAsTFa8&t=3s

and this article:

http://jakeboxer.com/blog/2009/12/13/the-knuth-morris-pratt-algorithm-in-my-own-words/



http://www.cnblogs.com/zhangtianq/p/5839909.html

字符串匹配问题:

暴力解法


KMP算法_第1张图片

发现没匹配成功,移动短的P string

KMP算法_第2张图片


KMP

先写出prefix table,准确说叫 相同前后缀Table。

KMP算法_第3张图片

在哪个位置匹配不上,按照prefix table上的index,把string 的index对准匹配失败的地方。

KMP算法_第4张图片

Edit on July 31. 

有一个地方要非常注意,KMP算法中当有一个字符对不上的时候,查看的是prefix table里position j-1位置上的value。然后把pattern[value]对其第一个对不上的地方。花了很多时间一直在看这个例子以后我终于知道为什么work了,而且为什么是position j-1!

首先当 abaa 和abab对不上的时候,暴力解法是只把abab往右移动一位。但是KMP会移动两位,因为已经知道ab和ab是完全一样的。所以要怎么理解position j-1? 我的理解是,如果b和a对不上,那这个时候就应该看b前一个的字母的最长相同前后缀的长度了。 比如abaa 和abab. 没对上的前一个字母是a。 其实我们已经知道最后一个字母b前面所有字母之前都和text完全一一对应了。我们现在想让失败的case前几个字母要和Text对上.



The worst case complexity of Naive algorithm is O(m(n-m+1)). 因为最多要move entire string向右一格 n-m+1 次。 每次要对比m个字符。 

 Time complexity of KMP algorithm is O(n) in worst case.  n > m.


KMP算法_第5张图片


lps[i] = the longest proper prefix of pat[0..i]

which is also a suffix of pat[0..i].


Preprocessing 那一步是最难的, 研究半天发现 这个就是DP的思想来求的。

KMP算法_第6张图片
KMP算法_第7张图片


Examples of lps[] construction:

For the pattern “AAAA”,

lps[] is [0, 1, 2, 3]

这里的k 这个数代表的是previous longest prefix. 这个真的很难理解!

KMP算法_第8张图片

为什么要判断k>-1, 以及ndl[k+1] != ndl[i]?


首先明确一下最长前后缀的意思: 就是前面跟屁股一样。abacaba 前面和后面一样aba。

看下图: 我们假设以及求出前一个substring的最长前后缀,到现在这个现在新的letter的位置。我们想知道有没有可能整个string的前面, 跟尾巴【包含letter】是相等的,相等的话,最长前后缀就会在之前的基础上加一。

判断k>-1是因为如果之前的最长前后缀<=-1, 根本都没有过最长前后缀呢!

KMP算法_第9张图片

如果不相等的话,我们找到position为前一个最长前后缀那么大的地方开始,然后看看这个substring的最前半部分的下一个letter跟当前这个letter有没有一样。一样的话好歹我们的最长前后缀还能有一点东西不至于为0.  为什么取从position为前一个最长前后缀那么大的地方开始? 因为

首先前半部分跟后半部分是一样的,通过之前已知。也就是前半部分substring里的的最长前缀跟后半部分的最长后缀一样!所以我们想在这个基础上看看最后一个letter有没有办法组成更长的。


KMP算法_第10张图片

练习KMP的两道题1. strStr()    2. shortest Palindrome.


Edit on 8月12号凌晨

今天重新回顾KMP,又发现新知识。。。之前其实并没有理解KMP为什么要做一个Prefix Table.

Table里的每一个位置其实是str 从0到index位置的这个subproblem的最长前后缀的值。【也可以移动一格】。比如说abab,假设我们只看到aba 这个单词,他的最长前后缀是1. a 和a

假设我们看到abab,这个最长前后缀是0. 

但是比如 abaa和abab,b最后一个字母不match,我们要把第二个string的index 1的letter b对准abaa的index 3. 因为index 3是mismatch的地方。 之前的已经确认完全一样。又因为aba 这个subproblem的最长前后缀为1. 所以第一个字母a和最后一个字母a确定是一样的。所以可以把aba的第一个字母移动到aba的最后一个字母a的位置,也就导致了aba的b对准了abaa之前mismatch的position 3. 

这就是为什么我们要求出每个子substring的最大前后缀。

你可能感兴趣的:(KMP算法)