KMP
待匹配的字符串
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
a | b | a | a | c | a | b | a | b | c |
目标字符串
0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|
a | b | a | b | c |
Prefix Table
string P = “a b a b c”
Prefix Table |
---|
a |
a b |
a b a |
a b a b |
a b a b c |
Prefix Table 作用:在匹配字符串时,遇到匹配到中途出现错误从而需要进行回溯。如算法匹配到 a b a b x 处(x != c),发生错误。则要去判断x处之前字符串 a b a b最优的回溯点。
Max length of the same Prefix and Suffix
Prefix Table | Prefix | Suffix | Max length |
---|---|---|---|
a | - | - | 0 |
a b | a | b | 0 |
a b a | a , a b | a , b a | 1 |
a b a b | a , a b , a b a | b , a b , b a b | 2 |
Next Array
在匹配过程中,若出现 a b a b c 则匹配已经成功,所以可以忽略这种情况。并且当匹配在a b a b x出现问题时,找的是 a b a b 的最大相同前后缀,所以将数组往下移动一位,第一个元素值置为-1
Index | -1 | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|---|
字符 | - | a | b | a | b | c |
Next Value | - | -1 | 0 | 0 | 1 | 2 |
index = -1 位置是虚构的,是不存在的。
为什么直接跳到next就可以了?
Next表也可以理解为:该元素前的字符串的最长相同前后缀的前缀的下一个元素索引。所以直接取出next,后缀已经被匹配过,前缀==后缀,前缀就无须再次匹配。
当
a b a a c a b a b c
a b a b
b出错了则找 a b a 的最大相同前后缀,长度为1,索引是从0开始的,1就是该前缀的下一个元素。因为a b a 中的后缀a已经被匹配通过,且前缀和后缀是相同的,所以前缀a无需再次匹配,将前缀后的元素与出错点对齐即可。
即:
a b a a c a b a b c
-----a b a b
总结
- 计算next(由匹配过程中出错位置,定该位置前缀的最大相同前后缀,对齐前缀后一元素与出错位置,从而达到优化回溯的目的)
- 进行迭代与回溯
- 这类算法用语言很难解释,画个图更易于理解嗷~
代码实现
现在太晚辽,明天再肝。