字符串模式匹配算法——BF和KMP算法
在字符串S中定位/查找某个子字符串P的操作,通常称为字符串的模式匹配,其中P称为模式串。模式匹配有多种算法,这里我先看一下最常见的BF算法和KMP算法。
BF(Brute—Force)算法
BF(Brute Force)算法也就是传说中的“笨办法”,是一个暴力/蛮力算法。设串S和P的长度分别为m,n,则它在最坏情况下的时间复杂度是O(m*n)。BF算法的最坏时间复杂度虽然不好,但它易于理解和编程,在实际应用中,一般还能达到近似于O(m+n)的时间度(最坏情况不是那么容易出现的,RP问题),因此,还在被大量使用。
1 | /** |
KMP算法
KMP算法,它是由D.E.Knuth、J.H.Morris和V.R.Pratt同时发现的。KMP算法可以在O(m+n)的时间里完成串的模式匹配。它的主要思想是:每当一趟匹配过程中出现字符不匹配时,不需回退i指针,而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的一段距离后,继续匹配过程。
对于KMP算法来说,核心是next数组的计算。next数组中每个值为模式字符串P中每个字符位置的真前缀和真后缀公共部分的最大长度。( “真前缀”指除了自身以外,一个字符串的全部头部组合;”真后缀”指除了自身以外,一个字符串的全部尾部组合,这里加这个强调是为了区分与我们普通意义上的”前缀“和”后缀“)
1 | function getNext (str) { |
KMP优化
KMP算法(未优化版): next数组表示最长的相同真前后缀的长度,我们不仅可以利用next来解决模式串的匹配问题,也可以用来解决类似字符串重复问题等等。
KMP算法(优化版):优化后的next仅仅表示相同真前后缀的长度,但不一定是最长(称其为“最优相同真前后缀”更为恰当)。此时我们利用优化后的next可以在模式串匹配问题中以更快的速度得到我们的答案(相较于未优化版),但是上述所说的字符串重复问题,优化版本则束手无策。
1 | function getNext (str) { |