28. 实现 strStr()
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
思路:
实现字符串匹配的关键是构建next数组,因此常规步骤就是构建next数组,然后再进行字符串的比对
1.构建next数组:定义指针j指向前缀末尾,i指向后缀末尾,即j=0,i=1,并且用for循环遍历i,然后对j、i所指向内容进行比对,如果不一致,则j回退到next数组i指向内容的后一个,如果一致则j++,并另next[i] = j
2.主串与模式串匹配:定义两个指针,分别指向两个字符串的首位,依次向后比较,遇到不一致则j指针去next数组找回跳的索引,然后继续比对,直到j指针指向模式串的长度末尾,此时则代表主串包含模式串,用主串指针i 减去 模式串长度再加1则可找到第一次匹配成功时索引的位置。
class Solution {
public int strStr(String haystack, String needle) {
if(needle.length() == 0) return 0;
int[] next = new int[needle.length()];
int j = 0 ;
getNext(next,needle);//记得调用getNext()
for(int i = 0;i <haystack.length() ; i++){
while( j>0 && needle.charAt(j) != haystack.charAt(i))
j = next[j-1];
if(needle.charAt(j) == haystack.charAt(i))
j++;
if(j == needle.length()) return i - needle.length() +1;
}
return -1;
}
public void getNext(int[] next,String needle){
int j = 0;//前缀末尾
next[0] = 0;//记得初始化
for(int i = 1;i < needle.length();i++){//i为后缀末尾,后缀不能包含首字母,因此从1开始
while( j>0 && needle.charAt(j) != needle.charAt(i)){
j = next[j-1];
}
if(needle.charAt(j) == needle.charAt(i)){
j++;
next[i] = j;
}
}
}
}
note:(getNext函数定义顺序)
1.先对next数组初始化
2.先处理不相等的情况,而且不相等可能不止一次,因此不能用if,要用while
3.后处理相等的情况,j++后,也要对next数组赋值