LeetCode—Implement strStr()

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;
	}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值