【代码随想录 字符串6.实现strstr】 KMP算法。
class Solution {
public int strStr(String haystack, String needle) {
//1.先求next数组
int[] next = new int[needle.length()];
getNext(next, needle);
//2.根据next数组匹配
int j = 0;
for (int i = 0; i < haystack.length(); i++) {
//如果当前不匹配,根据next数组进行回退j的位置.回退可能有多次,要用while
while ( j>0 && haystack.charAt(i) != needle.charAt(j)){
j=next[j-1];
}
//如果文本串和模式串当前字符一致,则进行下一位匹配
if(haystack.charAt(i) == needle.charAt(j)) {
j++;
}
//全部匹配完整,返回。根据当前i的值减去模式串的长度即可
if (j == needle.length()) {
return i-needle.length()+1;
}
}
return -1;
}
private static void getNext(int next[], String needle) {
//失败后寻找数组前一个,
int j = 0; //
next[0] = 0;
for (int i = 1; i < needle.length(); i++) {
//1. next[j] != next[i] ,j要进行回退。j如果等于0就没有回退的必要。
//这里有可能不是回退一次,是多次,所以要进行while循环
while ( j > 0 && needle.charAt(j) != needle.charAt(i)) {
//j跳转
j = next[j - 1];
}
if (needle.charAt(j) == needle.charAt(i) ) {
j++;
}
//这里的j是用于回退的,i才是表示字符串中的具体下标,即为next下标,所以为i赋值。
next[i] = j;
}
}
}
具体的解释可以看题解。
注意的点:
1.
代码:
while ( j>0 && haystack.charAt(i) != needle.charAt(j)){
j=next[j-1];
}
必须要在代码:
if(haystack.charAt(i) == needle.charAt(j)) {
j++;
}
之前,因为 if(haystack.charAt(i) == needle.charAt(j)) { j++; }
中对j进行了修改,如果此时再进行while代码的话,就不是从当前的条件来进行判断了。
2.
while ( j>0 && haystack.charAt(i) != needle.charAt(j)){
j=next[j-1];
}
对于这种代码,一定要先判断 j>0
,因为后面的判断条件涉及到数组下标,可能出现j小于0的情况,发生数组越界,程序报错。