算法14 leetcode28 实现 strStr() kmp
用indexOf()就没意思了
题目
实现 strStr() 函数。
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1 。
说明:
当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。
示例 1:
输入:haystack = "hello", needle = "ll"
输出:2
示例 2:
输入:haystack = "aaaaa", needle = "bba"
输出:-1
示例 3:
输入:haystack = "", needle = ""
输出:0
提示:
0 <= haystack.length, needle.length <= 5 * 104
haystack 和 needle 仅由小写英文字符组成
作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/xnr003/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我的双指针
和滚动窗口大同小异
class Solution {
public int strStr(String haystack, String needle) {
if(needle=="") return 0;
char[] h=haystack.toCharArray();
char[] n=needle.toCharArray();
for(int i=0;i<h.length;i++){
if(h[i]==n[0]){
int d=0;
int a=i;
for(;((d<n.length)&&a<h.length);a++,d++){
if(h[a]!=n[d]) break;
else if (d==n.length-1) return a-d;
}
}
}
return -1;
}
}
滚动窗口(参考)
class Solution {
public int strStr(String haystack, String needle) {
int windowSize = needle.length();
if (windowSize == 0) {
return 0;
}
int j = 0;
for (int i = 0; i < haystack.length(); i++) {
if (haystack.charAt(i) == needle.charAt(j)) {
if (j == windowSize - 1) {
return i - windowSize + 1;
}
j++;
} else {
i -= j;
j = 0;
}
}
return -1;
}
}
参考KMP
想弄明白KMP,这篇文章讲的比较好 https://blog.csdn.net/v_july_v/article/details/7041827
public int strStr(String haystack, String needle) {
if (needle.length() == 0)
return 0;
int i = 0;
int j = 0;
int[] next = new int[needle.length()];
getNext(needle, next);
while (i < haystack.length() && j < needle.length()) {
/**
* 这里j等于-1的时候也只有在下面next数组赋值的时候才会出现,并且只有在数组next[0]的时候才会等于-1,
其他时候是没有的,这一点要谨记,待会下面求next数组的时候就会用到。这里可以这样来理解,如果j不等于-1,
并且下标i和j所指向的字符相等,那么i和j分别往后移一位继续比较,这个很好理解,那么如果j==-1的时候,就表示
就表示前面没有匹配成功的,同时i往后移一位,j置为0(j==-1的时候,j++为0),再从0开始比较。
*/
if (j == -1 || haystack.charAt(i) == needle.charAt(j)) {
i++;
j++;
} else {
/**
* i = i - j + 1;
j = 0;
返回到指定的位置,不是返回到匹配失败的下一个位置,这里都好理解,重点是求数组next。
这里只要j等于0,在next[j]赋值的之后,j就会等于-1;因为next[0]等于-1
*/
j = next[j]; // j回到指定位置
}
if (j == needle.length())
return i - j;
}
return -1;
}
private void getNext(String p, int next[]) {
int len = p.length();
int i = 0;
int j = -1;
next[0] = -1;//这个默认的,
/**
* 匹配的时候是当前字符的前一个和前面的匹配,所以最后一个是不参与匹配的,可以看strStr方法的注释,
*/
while (i < len - 1) {
if (j == -1 || p.charAt(i) == p.charAt(j)) {
/**
* 如果j不等于-1,指定的字符相等,那么i和j要往后移一位,这点很好理解,如果j为-1的时候,i往后移移位,j置为0
* 重新开始匹配。next[i]是匹配成功的数量
*/
i++;
j++;
next[i] = j;
} else
/**
* 关键是这里不好理解,为什么匹配失败要让next[j]等于j,要记住这里的next[j]是指匹配成功的数量,有可能为0,也有可能是其他数.比如
* 字符串ABCABXYABCABATDM,对应的next数组为{-1 0 0 0 1 2 0 0 1 2 3 4 5 1 0 0 }
*/
j = next[j];
}
}