马拉车算法 kmp golang 版本

暴力破解版

func voKmp(txt, pat string) int {
	n := len(txt)
	m := len(pat)
	for i := 0; i < n-m; i++ {
		j := 0
		for j = 0; j < m; j++ {
			if pat[j] != txt[i+j] {
				break
			}
		}
		if j == m {
			return i
		}
	}
	return -1
}

马拉车 不走回头路 记录已经匹配的相同前缀

  • 使用有限确定状态机
func kmp(pat string) [][]int {
	m := len(pat)
	dp := make([][]int, m)
	dp[0] = make([]int, 256)

	dp[0][int(pat[0])] = 1
	x := 0
	for j := 1; j < m; j++ {
		dp[j] = make([]int, 256)
		for c := 0; c < 256; c++ {
			
			//if int(pat[j]) == c {
			//	dp[j][c] = int(j + 1)
			//}else{
			//	dp[j][c] = int(dp[x][c])
			//}
			
			// 状态回退
			dp[j][c] = int(dp[x][c])
		}

		// 转为下一个状态
		dp[j][int(pat[j])] = int(j + 1)

		// 更新相同前缀状态
		x = dp[x][int(pat[j])]
	}
	return dp
}

实现查找

func search(txt, pat string, dp [][]int) int {
	j := 0
	m := len(pat)
	n := len(txt)
	for i := 0; i < n; i++ {
		j = dp[j][int(txt[i])]
		if j == m {
			return i + 1 - m
		}
	}
	return -1
}

验证

	m := "aaab"
	n := "aaacaaab"
	fmt.Println(search(n, m, kmp(m)))
posted @ 2022-07-05 16:08  vx_guanchaoguo0  阅读(39)  评论(0编辑  收藏  举报