Topic: Hard Mode
Question:
Implement strStr().
Returns a pointer to the first occurrence of needle in haystack, or null if needle is not part of haystack.
» Solve this problem
方法:
简单的办法是两层循环,一个大循环,一个小循环,如果小循环的范围内不能匹配,那么大循环从小循环的起始位置下一个重新遍历。
另一种方法:KMP,很复杂的算法。计算needle的覆盖率,然后循环结合覆盖率可以使大循环不用重新返回的多与步骤。
参考:http://blog.csdn.net/v_july_v/article/details/6111565
Code:
class Test{
public static void main(String[] args){
String s1 = "cdeababcfgcabcz";
String s2 = "abc";
KmpString ks = new KmpString();
//求第一个s2在s1中出现的位置
System.out.println(ks.norStr(s1, s2));
System.out.println(ks.kmpStr(s1, s2));
}
}
class KmpString{
//简单算法
public int norStr(String s1, String s2){
int res = -1;
if(s1.length() < s2.length()) return -1;
for(int i=0; i<s1.length()+1-s2.length(); i++){
if(s1.charAt(i) == s2.charAt(0)){
res = check(s1, s2, i);
if(res == -1) continue;
else return res;
}
}
return res;
}
private int check(String s1, String s2, int index){
for(int i=0; i<s2.length(); i++)
if(s1.charAt(index+i) != s2.charAt(i))
return -1;
return index;
}
//KMP算法
public int kmpStr(String target, String pattern){
int[] overLay = iniOverLay(pattern);
int t = 0, p = 0;
while(t<target.length() && p<pattern.length()){
if(target.charAt(t) == pattern.charAt(p)){
t++;
p++;
}
else if(p == 0) t++;
else p = overLay[p-1]+1;
}
if(p == pattern.length()) return t-p;
else return -1;
}
private int[] iniOverLay(String pattern){
char[] pat = pattern.toCharArray();
int[] overLay = new int[pat.length];
int index = -1;
overLay[0] = -1;
for(int i=1; i<pat.length; i++){
index = overLay[i-1];
while(index>=0 && pat[index+1]!=pat[i])
index = overLay[index];
if(pat[index+1] == pat[i])
overLay[i] = index + 1;
else
overLay[i] = -1;
}
return overLay;
}
}
Code.2 Leetcode之Implement strStr()
public class Solution {
public String strStr(String haystack, String needle) {
// Start typing your Java solution below
// DO NOT write main() function
if(needle.length()==0) return haystack;
int[] overLay = getOverLay(needle);
int big = 0, small = 0;
while(big<haystack.length() && small<needle.length()){
if(haystack.charAt(big)==needle.charAt(small)){
big++;
small++;
}
else if(small == 0) big++;
else small = overLay[small-1]+1;
}
if(small==needle.length()) return haystack.substring(big-small);
else return null;
}
private int[] getOverLay(String needle){
char[] pat = needle.toCharArray();
int[] overLay = new int[pat.length];
overLay[0] = -1;
int index = -1;
for(int i=1; i<pat.length; i++){
index = overLay[i-1];
while(index>=0 && pat[index+1]!=pat[i])
index = overLay[index];
if(pat[i] == pat[index+1])
overLay[i] = index+1;
else
overLay[i] = -1;
}
return overLay;
}
}
我们拿第二个KMP算法来解释,index的意义是当前所在“序列”的当前位置出现在needle的第一个位置的数值。好吧。
另一个难点是while循环(求overLay的while),他的目的是让index回到上一个(更彻底的说是第一个)所出现的位置。
最后,
else small = overLay[small-1]+1;
这句话的意思是needle的指针small指向上needle中上一个当前元素的位置,其实,等同于small=overLay[small]但是防止返回为零,所以改变了写法,另外结合这句的上一个判断条件就不难理解。