實現 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 }