本体是比较经典的KMP算法的题目,这题可以有两种方法解决:暴力法和KMP
1.暴力法
定义一个 i 和 j 分别遍历两个字符串,初始化都为0,若不相等 i 就前进一步,直至相等停止前进,此时用while循环遍历接下来的元素是否相等,若遍历完整个字符串则返回对应的下标值。
代码如下:
public int strStr(String haystack, String needle) {
for(int left=0;left<haystack.length();left++){
char ch = haystack.charAt(left);
if(ch==needle.charAt(0)){
int right = left;
int index = 0;
while(right<haystack.length()&&index<needle.length()){
if(haystack.charAt(right)!=needle.charAt(index)){
break;
}
right++;
index++;
}
if(index==needle.length()){
return left;
}
}
}
return -1;
}
2.KMP
在kmp算法中,规定了next数组用来存放前缀表,若遇到不同的字母时,可以直接跳转到对应的位置,并继续进行遍历,省去了从头遍历的时间。
next数组求解过程(拿别人的哈哈哈):
每次取相同长度的前后缀子串对比是否相同,存在就返回前后缀子串长度,不存在都是0.
a:前后缀都为0,长度为0;
aa:前后缀都为a,长度为1;
aab:前缀aa,后缀ab,不相同,再取前缀a,后缀b,不相同,长度为0;
aaba:前缀aab,后缀aba,不相同,再取前缀aa,后缀ba,不相同,再取前缀a,后缀a,相同,长度为1;
aabaa:前缀aaba,后缀abaa,不相同,再取前缀aab,后缀baa,不相同,再取前缀aa,后缀aa,相同,长度为2;
aabaaf:前缀aabaa,后缀abaaf,不相同,再取前缀aaba,后缀baaf,不相同,再取前缀aab,后缀aaf,不相同,再取前缀aa,后缀af,不相同,再取前缀a,后缀f,不相同,长度为0.
解题步骤:
- 先定义一个方法,用来获取模式串的前缀表,具体思路看这个视频
- 获取到前缀表后,遍历两个字符串,在遇到不相同字符串的情况时,利用next数组确定模式串下一个待遍历元素的位置。
- 若模式串遍历完毕,则返回下标。
代码如下:
public int strStr(String haystack, String needle) {
if(needle.length()==0){
return 0;
}
int[] next = new int[needle.length()];
getNext(next,needle);
int j=0;
for(int i=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==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++){
while(j>0&&needle.charAt(j)!=needle.charAt(i)){
j=next[j-1];
}
if(needle.charAt(j)==needle.charAt(i)){
j++;
}
next[i]=j;
}
}