KMP Implement
KMP
KMP 的思想
kmp的思想就是当出现字符串不匹配的情况时,可以知道一部分之前已经匹配的文本内容,利用这些信息避免从头再去匹配
怎么记录之前已经匹配的内容 ?
一般使用前缀表来做记录
前缀表 : 记录了模式串 和 文本串 不匹配的时候, 模式串应该从哪里开始重新匹配的信息
案例 (下文所有都会拿这两个举例):
文本串 : 【 a a b a a b a a f a】
模式串 : 【 a a b a a f】
有关前缀表
什么是前缀 ?
字符串中前缀是指 不包含最后一个字符的所有以第一个字符开头的连续子字符串
以模式串为例
【a a b a a f】
它的前缀有
[ a ]
[ a a ]
[ a a b ]
[ a a b a]
[ a a b a a]
什么是后缀 ?
字符串中后缀是指 不包含第一个字符的所有以最后一个字符结尾的连续子字符串
以模式串为例
【a a b a a f】
它的后缀有
[ f ]
[ a f ]
[ a a f ]
[ b a a f ]
[ a b a a f ]
最长相等前后缀
以模式串为例
【a a b a a f】 那么这个的最长相等连续字串就是 0
如果是【a a】 那么它的最长相等连续字串就是 1
如果是【a a b】 那么它的最长相等连续字串就是 0
如果是【a a b a 】 那么它的最长相等连续字串就是 1
如果是【a a b a a】 那么它的最长相等连续字串就是 2
得到前缀表
下标 :[ 0 1 2 3 4 5 ]
模式串: [ a a b a a f ]
前缀表: [ 0 1 0 1 2 0 ] ——> 我们得到前缀表就是 最长相等前后缀 ,也就是最长相等连续子串
如何利用前缀表找到字符不匹配时指针应该移动的位置
文本串 : 【 a a b a a b a a f a】
下标 : 【 0 1 2 3 4 5…】
模式串 : 【 a a b a a f 】
前缀表 : 【 0 1 0 1 2 0】
根据不匹配的前一位即前面匹配的那一位的最长相等前后缀的next[i] 的值 和 上面的文本串的下标 进行匹配 ,从而找到指针应该移动的位置
从上面的图中 我们就可以得到 在 文本串的【索引 5】 的地方开始就无法匹配 , 那么我们要找的就是【索引 4】所对应的前缀表的数值
与之对应的值 为 2 那么我们就从文本串中找到下标为 2 的,从那里开始重新匹配
实现KMP
构造前缀表
1 | public void getNext(String s , int[] next){ |
用前缀表来匹配数组
找出文串中 模式串第一个字符的位置(从 0 开始)
答 : 返回当前在文本串匹配的最后一个位置 i , 然后再减去模式串的长度 ,就是文本串中模式串的第一个字符的位置
1 |
|