KMP算法

64 阅读2分钟

重新看了下卡哥的KMP相关的文章,感觉比之前看到了之后要更清晰了一点。

KMP主要应用在字符串匹配上。

KMP的主要思想是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。

KMP算法的实现要依赖于字符串的最长相等前后缀。
前缀就是含有第一个字符但不包含最后一个字符的所有连续子串。
后缀与前缀相反,是一定含有最后一个字符但不含有第一个字符的连续子串。

我们需要通过前后缀来维护一个前缀表,前缀表的实现形式可能会有所不同但本质相同,就是表示某位置的子串的最长相等前后缀的长度是多少。

为什么要用前缀表?
使用前缀表我们可以跳过一些相同的部分进而提升匹配的速度。当标准串和匹配串出现不一致的情况后,就可以查看标准串中该位置的前一个位置的前缀表的值,也就是查找不匹配位置前面的部分有多少和最开始想匹配,这样就能跳过那些相等的字符串,提升我们是查找效率。

获取前缀表/next数组的实现
主要分成四步

  1. 初始化
  2. 不相等的情况
  3. 相等的情况
  4. next

这里的实现需要使用双指针,i指向子字符串的末尾,j指向相等的前缀末尾,j也是最长相等前后缀的值。

getnext(int next[],String s){
//初始化,j要初始化为0,最开始只有一个字符的子字符串的前后缀长度也为0,i应该从1开始
int j=0;
next[0] =0;

for(int i=1;i < s.length ;i++){
//不相等的情况,回退,就是跳到前一个位置最近的相等的子串再接着匹配,就是尽量找长度最长的匹配字符串长度
while(j >0 && s.charAt(j) != s.charAt(i)){
j = next[j-1];
}
//相等的情况,继续向后比较
if(s.charAt(j) == s.charAt(i)){
j++;
}
//记录当前的位置。
next[i] = j;
}
}