题目描述
Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
Example 1:
Input: haystack = “hello”, needle = “ll”
Output: 2
Example 2:
Input: haystack = “aaaaa”, needle = “bba”
Output: -1
Clarification:
What should we return when needle is an empty string? This is a great question to ask during an interview.
For the purpose of this problem, we will return 0 when needle is an empty string. This is consistent to C’s strstr() and Java’s indexOf().
在haystack字符串中寻找等于needle的子串,返回第一次出现该子串的下标
思路
- 暴力查找,即Brute-Force,逐个遍历haystack字符串,直到找到和needle相等的子串
使用Java库函数substring找子串,超方便! - KMP,比较重要的字符串匹配算法,但算法过程较繁琐
实现
BF
public int strStr(String haystack, String needle) {
//BF(利用Java中库函数substring寻找匹配的子串)
int l1=haystack.length();
int l2=needle.length();
//特殊情况:needle为空串的话,返回0
if(needle.equals("")) return 0;
int gap=l1-l2; //gap指haystack和needle字符串长度的差距
//从haystack第一个元素开始找,一直找到最后只剩下needle的长度(hello下标从0找到3,最后剩一个元素留给可能的needle元素)
for(int i=0;i<=gap;i++){ //如果haystack存在子串等于needle,则返回子串首元素的下标i
if(haystack.substring(i,i+l2).equals(needle)) return i;
}
return -1; //不满足上述情况说明不存在子串,返回-1
}
KMP:
这是几个月前通过的KMP代码,之前好不容易搞懂了KMP,过了几个月又忘了,心痛~
//求最长公共前后缀:逐步判断 i,j位置上的元素是否相同---
//同: i++,j++(j位置前进),且相应的next[]值=j++
//不同:i++,j看j前面那个元素的next[]值,退回到这个值,退完再比较i,j位置上的元素。。。以此类推
public static int[] kmpnext(String needle){
int[] next=new int[needle.length()];
try {
next[0]=0;
}catch(Exception e) {
e.getMessage();
}
for(int j=0,i=1;i<needle.length();i++){
while(j>0 && needle.charAt(i) !=needle.charAt(j)){
j=next[j-1];
}
if(needle.charAt(i) ==needle.charAt(j)){
j++;
}
next[i]=j;
}
return next;
}
/*从头开始比较,若两个字符串元素 同:i++,j++,继续向后比较
* 不同:不回开头重新比较,而是跳过一段没有必要的匹配---->
* 子串下标 j退回到其next[j-1]这个值即可和 母串上次中断的置 继续比较
*
*/
public int strStr(String haystack, String needle) {
if(needle.length()==0) return 0;
int[] next=kmpnext(needle);
try {
for(int i=0,j=0;i<haystack.length();i++) {
while(j>0 && haystack.charAt(i) != needle.charAt(j)) { //两个字符串元素不同,
j=next[j-1]; //子串下标 j退回到其next[j-1]这个值
}
if(haystack.charAt(i) == needle.charAt(j)) {
j++;
}
if(j==needle.length()) { //如果比较到了子串最后一个字符,即比较结束了
return i-j+1; //返回子串在母串中第一次出现的位置下标
}
}
}catch(Exception e) {
e.getMessage();
}
return -1;
}