问题:
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
解答:
class Solution {
public int strStr(String haystack, String needle) {
if (needle.length() == 0) {
return 0;
}
int i = 0; // 主串中的指针
int j = 0; // 子串中的指针
int[] next = build_next(needle); // 算出的next数组
while (i < haystack.length() && j < needle.length()) {
if (haystack.charAt(i) == needle.charAt(j)) {
// 字符匹配,指针后移
i++;
j++;
} else if (j > 0) {
// 字符未匹配,根据 next 跳过子串前面的一些字符
j = next[j -1];
} else {
// 子串第一个字符就未匹配
i++;
}
}
if (j == needle.length()) {
// 匹配成功
return i - j;
} else {
// 匹配失败
return -1;
}
}
private int[] build_next(String needle) {
int len = needle.length();
int[] next = new int[len]; // 创建next数组
next[0] = 0;
int prefix_len = 0; // 当前共同前后缀的长度
int i = 1;
while (i < len) {
if (needle.charAt(prefix_len) == needle.charAt(i)) { // 检查当前字符和下一个字符是否相同
/**
* 当前字符和下一个字符相同
* 共同前后缀长度加1-->prefix_len++
* 将当前共同前后缀长度赋值为数组中-->next[i] = prefix_len
* 继续递增-->i++
*/
prefix_len++;
next[i] = prefix_len;
i++;
} else if (prefix_len == 0) { // 当前字符和下一个字符相同,检查是否有更短的共同前后缀
// 没有更短的共同前后缀,next直接设置为0
next[i] = 0;
i++;
} else {
// 有更短的共同前后缀,直接查询获得
prefix_len = next[prefix_len - 1];
}
}
return next;
}
}
想更详细了解KMP算法的可参考:【最浅显易懂的 KMP 算法讲解】