【字符串】leetcode28——实现strStr()(KMP)

编号28:实现 strStr()

实现 strStr() 函数。html

给定一个 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() 定义相符。函数

思路

本题是一道经典的KMP算法题,KMP的经典思想就是:「当出现字符串不匹配时,能够记录一部分以前已经匹配的文本内容,利用这些信息避免从头再去作匹配。」code

你们能够看看这一篇了解[KMP算法]htm

这里为了方便,咱们将haystack称为文本串,将needle称为模式串blog

首先构造模式串的next[]数组字符串

//当前字符串冲突时回退到前一位next数组对应的值
func getNext(next []int, s string) {
	//初始化
	j := 0
	next[0] = 0
	for i := 1; i < len(s); i++ {
		//先后缀不相同的状况
		for j > 0 && s[i] != s[j] {
			j = next[j-1] //回退
		}
		//先后缀相同的状况
		if s[i] == s[j] {
			j++
		}
		next[i] = j
	}
}

获得next[]数组以后,咱们就能够开始匹配了get

//进行匹配:为了方便,将haystack字符串称为文本串,将needle字符串称为模式串
func strStr(haystack string, needle string) int {
	//若是模式串为空串 则返回0
	if len(needle) == 0 {
		return 0
	}

	//求解模式串的next数组
	next := make([]int, len(needle))
	getNext(next, needle)

	j := 0 // next[]数组中记录的起始位置为0

	//开始匹配
	for i := 0; i < len(haystack); i++ {
		for j > 0 && haystack[i] != needle[j] { //字符不匹配的状况
			j = next[j-1] //这里j要找前一位回退的位置
		}
		//字符匹配状况,i,j下标都++
		if haystack[i] == needle[j] { //i在for循环中++
			j++
		}

		//判断匹配结束 即下标j为模式串的长度,则当前文本串包含该模式串
		if j == len(needle) {
			return i - len(needle) + 1
		}
	}

	//文本串不包含模式串
	return -1
}

这应该是标准的KMP求解比较通俗易懂的方法啦~

完整代码以下(看着很长,可是是按照流程来的,理解很方便):

//求解next[]数组
func getNext(next []int, s string) {
	//初始化
	j := 0
	next[0] = 0
	for i := 1; i < len(s); i++ {
		//先后缀不相同的状况
		for j > 0 && s[i] != s[j] {
			j = next[j-1] //回退
		}
		//先后缀相同的状况
		if s[i] == s[j] {
			j++
		}
		next[i] = j
	}
}

//进行匹配:为了方便,将haystack字符串称为文本串,将needle字符串称为模式串
func strStr(haystack string, needle string) int {
	//若是模式串为空串 则返回0
	if len(needle) == 0 {
		return 0
	}

	//求解模式串的next数组
	next := make([]int, len(needle))
	getNext(next, needle)

	j := 0 // next[]数组中记录的起始位置为0

	//开始匹配
	for i := 0; i < len(haystack); i++ {
		for j > 0 && haystack[i] != needle[j] { //字符不匹配的状况
			j = next[j-1] //这里j要找前一位回退的位置
		}
		//字符匹配状况,i,j下标都++
		if haystack[i] == needle[j] { //i在for循环中++
			j++
		}

		//判断匹配结束 即下标j为模式串的长度,则当前文本串包含该模式串
		if j == len(needle) {
			return i - len(needle) + 1
		}
	}

	//文本串不包含模式串
	return -1
}
相关文章
相关标签/搜索