kmp算法的核心是理解next数组的含义。
next数组规则如下:
注意,下标
j
从
1
开始,到最后一个字符结束
(
也可以是
0
,但是其他值都减
1
)
\color{red}注意,下标j从1开始,到最后一个字符结束(也可以是0,但是其他值都减1)
注意,下标j从1开始,到最后一个字符结束(也可以是0,但是其他值都减1)
- next[j] = 1 , j = 1
- 满足如下条件的k的最大值:
n e x t [ j ] = { m a x ( k ) ∣ 1 < k < j , p 1 . . . p k − 1 = p j − k + 1 . . . p j − 1 } 。 其中 0 < p 1 ≤ p k − 1 , 0 < p j − k + 1 ≤ p j − 1 。 next[j] = \{max(k) \quad | 1<k <j,p_1...p_{k-1} = p_{j- k + 1}...p_{j-1}\}。\\其中0<p_1 \le p_{k - 1}, 0 < p_{j-k+1} \le p_{j - 1} 。 next[j]={max(k)∣1<k<j,p1...pk−1=pj−k+1...pj−1}。其中0<p1≤pk−1,0<pj−k+1≤pj−1。 - next[j] = 1,其他情况。
查找时,若在主串中找到模式串的部分匹配,为了不回退主串中的比较指针,从而提高查找/比较速度,从而采取的优化措施。特别是在模式串比较长,比如超过几十个字符,并且模式串中出现重复的前缀和后缀时,kmp算法能极大提高速度,模式串中:模式串越长并且前后缀匹配越长,算法的时间复杂度提升越明显。
比如字符串"abaabcac"的next数组为:111223121
至于改进的next数组,情况将会更加复杂。
关于卡特兰数,暂时只需要记忆如下公式,推导暂且不提:
C 2 n n n + 1 \frac{C_{2n}^{n}}{n+1} n+1C2nn