【字符串】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
}
相關文章
相關標籤/搜索