原理
next 数组存放的是当前长度下的 最长相同前后缀 的长度
next数组的应用
-
当C和F不匹配时,怎么回退呢?答案是找到上一个
因为上一个肯定是已经匹配完成的字母,我们找到它对应的 next 数组值来指导我们进行下一步操作
那么问题来了,现在 next 数组值 2代表什么呢?它想让我们干什么呢?
那么问题来了,现在 next 数组值 2代表什么呢?它想让我们干什么呢?
那么问题来了,现在 next 数组值 2代表什么呢?它想让我们干什么呢?
2表示当前已经匹配的子字符串 abcab的最长相同前后缀长度是 2,而我们数组下标是从 0️⃣开始的,如果我们按照 2的指示,正好可以跳转到下标 2 的位置(也就是字母C),开始下一次匹配。
前缀的应用场景是匹配串;
而后缀的应用场景是原字符串;
!!!!next 数组记录了我们的最长相同前后缀,在这里派上用场!!!!
我们也就确定了 C 前面的字母已经匹配,可以放心的匹配之后的字母了
求next数组
for (int right = 1, left = 0; right < needleLength; right++) {
// 定义好两个指针right与left
// 在for循环中初始化指针right为1,left=0,开始计算next数组,right始终在left指针的后面
while (left > 0 && needle.charAt(left) != needle.charAt(right)) {
// 如果不相等就让left指针回退,到0时就停止回退
left = next[left - 1];//进行回退操作;
}
if (needle.charAt(left) == needle.charAt(right)) {
left++;
}
next[right] = left;
// 这是从 1 开始的
}
// 循环结束的时候,next数组就已经计算完毕了
KMP算法实现
class Solution {
public int strStr(String haystack, String needle) {
//自己敲一下子 前缀表不需要减一的实现方式
int needleLength = needle.length();
if (needleLength == 0) return 0;
// 当needle是空字符串时,返回0
int[] next = new int[needleLength];
// 定义好next数组
for (int right = 1, left = 0; right < needleLength; right++) {
// 定义好两个指针right与left
// 在for循环中初始化指针right为1,left=0,开始计算next数组,right始终在left指针的后面
while (left > 0 && needle.charAt(left) != needle.charAt(right)) {
// 如果不相等就让left指针回退,到0时就停止回退
left = next[left - 1];//进行回退操作;
}
if (needle.charAt(left) == needle.charAt(right)) {
left++;
}
next[right] = left;
// 这是从 1 开始的
}
// 循环结束的时候,next数组就已经计算完毕了
for (int i = 0,j=0; i <haystack.length() ; i++) {
while (j>0&&haystack.charAt(i)!=needle.charAt(j)){
j=next[j-1];
}
if (haystack.charAt(i)==needle.charAt(j)){
j++;
}
if (j==needleLength) return i-needleLength+1;
}
return -1;
}
}
next数组回溯详解
为什么要根据left = next[left - 1]
回退?
这时候我们的 left 指针应该怎么办呢?
left = next[left - 1];
最长前缀和最长后缀是最长相同前后缀,见图右半部分。
这时候,最长前缀变成 ab
,最长后缀因为要和最长前缀保持一致,也缩水成了 ab
。
接着将 left
指针指向的 e
和 right
指针指向的 e
进行对比,发现相等。
就更新了当前数组的 next 数组
个人认为写的最好的KMP算法图解:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/solutions/1119642/duo-tu-yu-jing-xiang-jie-kmp-suan-fa-by-w3c9c