leetcode- 28-实现strStr()(implement strstr)-java

题目及用例

package pid028;
/*实现strStr()

实现 strStr() 函数。

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回  -1。

示例 1:

输入: haystack = "hello", needle = "ll"
输出: 2

示例 2:

输入: haystack = "aaaaa", needle = "bba"
输出: -1

说明:

当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。




*/


public class main {
	
	public static void main(String[] args) {
		String [] testTable = {"hello","aaaaa","aa"};
		String [] testTable2 = {"ll","bba","aa"};
		for (int i=0;i<3;i++) {
			test(testTable[i],testTable2[i]);
		}
	}
		 
	private static void test(String ito,String ito2) {
		Solution solution = new Solution();
		int rtn;
		long begin = System.currentTimeMillis();
		System.out.println(ito);
		System.out.println(ito2);
		System.out.println();
		//开始时打印数组
		
		rtn= solution.strStr(ito,ito2);//执行程序
		long end = System.currentTimeMillis();	
		
		System.out.println("rtn" );
		System.out.print(rtn);
		System.out.println();
		System.out.println("耗时:" + (end - begin) + "ms");
		System.out.println("-------------------");
	}

}

解法一(成功,13ms,较慢)
使用for循环,对要检查的字符串从头到中间进行循环,每一次循环时,将循环查询的字符串的长度,从头到尾进行比对,如果成功,则大跳出循环,不成功,则跳出小循环,继续检验
在大循环中到中间,是因为如果到了后面,肯定不行,要检验的比查询的字符串都短,所以大循环到中间

package pid028;

import java.util.Arrays;

public class Solution {
public int strStr(String haystack, String needle) {
	int length1=haystack.length();
    int length2=needle.length();    
	if(length2==0){
		return 0;
	}
	if(length1==0||length1<length2){
		return -1;
	}
	int index=-1;
	int i=0;
	int j=0;
	for(i=0;i<length1-length2+1;i++){
		for(j=0;j<length2;j++){
			char now1=haystack.charAt(i+j);
			char now2=needle.charAt(j);
			if(now1!=now2){
				break;
			}
		}
		if(j==length2){
			index=i;
			break;
		}
		
	}	
	return index;
    }

}

解法二(别人的)
精妙的方法,思路和我的一模一样,但是for循环内不用临界值,只用三个判断搞定

public int strStr(String haystack, String needle) {

// 从heystack开始

for (int i = 0; ; i++) {

// 匹配needle的字符

for (int j = 0; ; j++) {

// 如果needle和j一样长,则直接返回i(当前匹配的起始位置),因为已经匹配成功了

if (j == needle.length()) { return i; }

// 如果i+j为当前haystack的长度,则表明已经走完heystack所有的字符,并且没有匹配成功(注意如果最后一个字符正好匹配成功,则在上面一个判断就会返回)

if (i + j == haystack.length()) { return -1; }

// 如果当前needle和haystack的字符相同的话(因为每次不成功匹配不成功,则i移动1位,而j又重新从0开始,所以haystack的当前位置是i+j)

if (needle.charAt(j) != haystack.charAt(i + j)) { break; } } } }

解法三(别人的,据说是大神算法)

在花了些功夫理解思想后,关于next数组的理解把我卡在了半路,又是各种搜,搜到pku的一个ACM PPT把我点通了,和之前博文的讲解串联了起来:
就是下面这个,举的例子来说明运行过程,
• i = 1 2 3 4 5 6 7 8 9 ……
• A = a b a b a b a a b a b …
• B = a b a b a c b
• j = 1 2 3 4 5 6 7
•当i=6,j=5时,a[i+1]!=b[j+1],故令j=next[5]=3
• i = 1 2 3 4 5 6 7 8 9 ……
• A = a b a b a b a a b a b …
• B = a b a b a c b
• j = 1 2 3 4 5 6 7
•此时i=6,j=1 仍不满足a[i+1]==b[j+1],故继续减小j,使j=next[1]=0
• i = 1 2 3 4 5 6 7 8 9 ……
• A = a b a b a b a a b a b …
• B = a b a b a c b
• j = 1 2 3 4 5 6 7
•终于,A[8]=B[1],i变为8,j为1
• i = 1 2 3 4 5 6 7 8 9 ……
• A = a b a b a b a d b a b …
• B = a b a b a c b
• j = 1 2 3 4 5 6 7
•事实上,有可能j到了0仍然不能满足A[i+1]=B[j+1](比如A[8]=“d”时)。因此,准确的说法是,当j=0了时,我们直接增加i值但忽略j直到出现A[i]=B[1]为止。
(PS:有一点小小的疑问,上面那里 i 的值是不是写错了,比如最上面那个,i值为7,j=5的时候吧?不过不影响整体的理解)
我认为有助于理解KMP思想的文章:
http://blog.csdn.net/yutianzuijin/article/details/11954939
这篇文最后作者还给了个科赫曲线,我开始真不理解为啥,懂了之后也就明白了,作者想借此表达一种局部的局部的思想吧,子串也就是pattern串不断向前缩短的同时,也存在着匹配的前缀和后缀。
http://www.cnblogs.com/goagent/archive/2013/05/16/3068442.html
这篇文关于next的公式和图讲的挺好的
http://blog.csdn.net/power721/article/details/6132380
这篇文用表格的形式描绘了一下匹配过程,也挺直观的。
其他的可以参考学习下的文:
http://www.cppblog.com/oosky/archive/2006/07/06/9486.html
http://blog.csdn.net/joylnwang/article/details/6778316

public int strStr(String haystack, String needle) {
        if(haystack==null || needle==null)    
            return 0;

	int h = haystack.length();
	int n = needle.length();

	if (n > h)
		return -1;
	if (n == 0)
		return 0;

	int[] next = getNext(needle);
	int i = 0;

	while (i <= h - n) {
		int success = 1;
		for (int j = 0; j < n; j++) {
			if (needle.charAt(0) != haystack.charAt(i)) {
				success = 0;
				i++;
				break;
			} else if (needle.charAt(j) != haystack.charAt(i + j)) {
				success = 0;
				i = i + j - next[j - 1];
				break;
			}
		}
		if (success == 1)
			return i;
	}

	return -1;
}

//calculate KMP array
public int[] getNext(String needle) {
	int[] next = new int[needle.length()];
	next[0] = 0;

	for (int i = 1; i < needle.length(); i++) {
		int index = next[i - 1];
		while (index > 0 && needle.charAt(index) != needle.charAt(i)) {
			index = next[index - 1];
		}

		if (needle.charAt(index) == needle.charAt(i)) {
			next[i] = next[i - 1] + 1;
		} else {
			next[i] = 0;
		}
	}

	return next;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值