题解
Go语言实现
核心:
- KMP其实就是dp变化,因此我们要让模式串
pat
产生相应的前缀影响的状态图 - 后面只需让字符串
txt
跳进这个状态图进行比较
package main
import "fmt"
type KMP struct {
dp [][]int
pat string
}
//创建一个模式串的状态图
func NewKMP(pat string) *KMP {
k := &KMP{
pat: pat}
M := len(pat)
//创建一个二维数组
k.dp = make([][]int, M)
for i := 0; i < M; i++ {
//256表示ASCII,后面传入的是char,所以要强制转换
k.dp[i] = make([]int, 256)
}
//初始状态
k.dp[0][int(pat[0])] = 1
//影子,表示最近的前缀
X := 0
for j := 1; j < M; j++ {
for c := 0; c < 256; c++ {
k.dp[j][c] = k.dp[X][c]
}
//符合下一个字符串,就要推进下一个状态
k.dp[j][int(pat[j])] = j + 1
//影子再次更新最近的前缀
X = k.dp[X][int(pat[j])]
}
return k
}
func (k *KMP) Search(txt string) int {
M, N := len(k.pat), len(txt)
j := 0
for i := 0; i < N; i++ {
j = k.dp[j][int(txt[i])]
if j == M {
//返回第一索引
return i - M + 1
}
}
//找不到,返回-1
return -1
}
func strStr(haystack string, needle string) int {
k := NewKMP(needle)
return k.Search(haystack)
}
func main() {
haystack, needle := "sadbutsad", "sad"
fmt.Println(strStr(haystack, needle))
}