KMP原理及使用的再总结
@(算法学习)
回顾之前写的文章,再看对其中的简单数学原理理解更深了。但是奇怪的是,看别人用有限自动机理论解释还是看不太懂,索性还是从这里起步推导为佳。
http://blog.csdn.net/u011240016/article/details/52372086?locationNum=1&fps=1
这篇主要说明了如何只根据模式串(待匹配的子串)自身推导得出下一个要比较的字符。
即使不熟悉KMP,记住一句话则非编码题可手动解出。
这句话是:当失配时,文本串中游走的指针仍然指向此次失配时的字符,而在模式串中,考虑回退,在过去找一个字符与文本串的这个字符匹配。当然,模式串中此字符及其前面所有的都与文本串当前指示的字符及其往前相同数目的字符相匹配。
总结成量化的语句是:
寻找的k值 = 模式串中失配字符之前的全部字符前缀和后缀相等的最大长度+1。
这里字符下标都是从1开始。
所以,失配时,只需要在模式串中,研究当前失配字符左边的全部字符(不含失配字符),前缀和后缀最大公共部分。模式串中下一个与文本串中失配字符比较的字符是此前缀后面的字符。
这是通过数学推导证明的。
比如:abaabc,在比较c时失配。则我们知道的信息其实很多了,即:前面的abaab已经匹配了。下一个与文本串失配字符比较的是谁呢?
根据上面的说法,看c以前的全部字符: ab⎯⎯⎯⎯aab⎯⎯⎯⎯ ,划线的ab是最大公共子串,因此,中间的a将是下一个与文本串比较的字符。
你看,我们都不知道文本串是什么,居然可以知道文本串失配的字符是什么!这就是数学在背后的作用。具体数学推导看上面的文章链接。下面是用题目实际验证。
看一个小题:
已知字符串S为abaabaabacacaabaabcc,模式串P为abaabc。采用KMP算法进行匹配,第一次出现“失配”( S[i]≠P[j] )时, i=j=5 ,则下次开始匹配时,i和j的值分别是:C。
A. i = 1, j = 0
B. i = 5, j = 0
C.i = 5, j = 2
D. i = 6, j = 2
分析:但凡有一点点对KMP思想的理解,就很容易排除A,D。因为文本串S在失配时指针不动。
剩下BC,而B显然是不对的,因为,我们目的是在失配时让模式串中指针往右游走更多距离。因为比较时已经看到了挺多字符,不用起来做一个快速的决策,实在过于浪费。
因此,单纯解此题而言,不用真正用KMP去求解,用基本思想就足够了。
而如果是动手解,不看选项的话,也很简单。但需要注意下标是从0开始的。但我们不必管。上面举的例子就是这题的解法。即abaabc比较到c失配了,该在模式串中选择的是第三个字符(P[2])与文本串比较。此时i = 5,S[5] = a.恰好相等。我们再往前看S[5]之前的是ab, P[2]之前的也是ab,即前面都是匹配的。从这里出发再往后进行比较即可。
所以i = 5(没变),j=2(指示下一个模式串的下标),此时S[i] = P[j]。这正是失配时问题的解决方案。
分析了一大段,最终得到的操作是很简单的比较前缀后缀。希望对你也有所帮助。
再以一个求next数组的例子思考这个问题:
模式串S = ‘abaabcac’
字符下标从1开始。
next[j] = k,表示在S[i]与P[j]失配时,用P[k]与S[i]继续比较。
next[1] = 0,next[2] = 1;
next[3], 此时比较到aba,在a处失配。因此看ab的前后缀,最长公共后缀长度是0,所以,next[3] = 1,即还从第一个字符开始比较。
next[4], 此时abaa,看aba的前缀后缀,有公共子串a,因此指向前缀a后面的字符b,即next[4] = 2(下标从1开始)
next[5],此时abaab,看abaa的前缀后缀,有公共子串a,因此也指向前缀a后面的字符b,即next[5] = 2
next[6],此时abaabc,看abaab的前缀后缀,有公共子串ab,因此指向前缀ab后面的字符a,即next[5] = 3
next[7],此时abaabca,看abaabc的前缀后缀,没有公共子串,因此指向第一个字符,即next[7] = 1
next[8],此时abaabcac,看abaabca的前缀后缀,有公共子串a,因此指向前缀a后面的字符b,即next[8] = 2.
所以:
编号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
S | a | b | a | a | b | c | a | c |
next | 0 | 1 | 1 | 2 | 2 | 3 | 1 | 2 |
这便是求解next数组的手动过程。老实说,用了一年才真正理解这个算法。一直不想不敢静下心来仔细思考背后的原理,只是想马上知道怎么用。
静下心来,美好的事情就要发生。