Description:Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.(判断字符串p是不是s的一个子串)。
首先,我们一定会想到使用暴力法解决这个问题。思路很简单,假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置,则有:
- 如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符;
- 如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0。相当于每次匹配失败时,i 回溯,j 被置为0。
代码如下:
public int strStr(String haystack, String needle) {
int neLen=needle.length();
int hayIndex=0,neIndex=0;
while(hayIndex<hayLen&&neIndex<neLen){
if(haystack.charAt(hayIndex)==needle.charAt(neIndex)){
hayIndex++;
neIndex++;
}
else{
hayIndex-=(neIndex-1);
neIndex=0;
}
}
if(neIndex==neLen)
return hayIndex-neLen;
else
return -1;
}
分析会发现,时间复杂度为o(m*n)(m,n分别为haystack,needle的长度)。那么可否在线性的时间内进行匹配了?答案是肯定的,我们可以使用KMP算法进行求解,KMP算法的解析可以查看JULY的博客从头到尾了解KMP算法,里面介绍的非常详细,讲的非常好,另外,还可以去维基百科查看资料,我写的这个算法的思路就是参考维基百科里面讲的。
先看看维基百科里面算法的伪代码:
我实现的代码
public int strStr(String haystack, String needle) {
if(needle.length()==0)
return 0;
if (haystack.length() == 0 ) return -1;
if(needle.length()>haystack.length()) return -1;
int m=0,i=0;
int[] t=computePrefix(needle);
while(m+i<haystack.length()){
if(needle.charAt(i)==haystack.charAt(i+m)){
if(i==needle.length()-1)
return m;
else
i++;
}
else{
if(t[i]>-1){
m=m+i-t[i];
i=t[i];
}
else{
<span style="white-space:pre"> </span>i=0;
m=m+1;
}
}
}
return -1;
}
private static int[] computePrefix(String needle){
int length=needle.length();
int[] t=new int[length];
if(needle.length()==1){
t[0]=-1;
return t;
}
t[0]=-1;
t[1]=0;
int k=0;
int i=2;
while(i<length){
if(needle.charAt(i-1)==needle.charAt(k)){
k++;
t[i]=k;
i++;
}
else if(k>0)
{ k=t[k];
t[i]=k;
}
else
{
t[i]=0;
i++;
}
}
return t;
}