KMP算法理解

本文介绍了如何使用KMP算法解决字符串匹配问题,重点讲解了最长公共前后缀的概念以及next数组的构建过程,这对于处理不完全匹配的字符串搜索至关重要。

最长公共前后缀

就是在前后缀中取最大的相同缀。比如对于字符串"abab",其前缀有a、ab、aba,后缀有b、ab、bab,显然最长公共前后缀就是ab

构建next

next[i]储存了在以i为开头的后缀,和以j为结尾的前缀匹配时,j的下一个位置。正如next名字所暗示的,下一个,而不是匹配的j本身

之所以储存下一个的原因在于,在进行匹配时,模式串要跳到上一个匹配成功的位置,而字符串本身不会移动,那么在这种情况下,当前字符串要匹配的就是已经匹配成功字符的下一个位置

func getNext(pattern string) []int {
	next := make([]int, len(pattern))
	// i指向后缀的开始,j指向前缀的结尾
	var j int
	for i := 1; i < len(pattern); {
		// 当i、j匹配时,那么在i不匹配时,就会直接跳到j的下一位,然后i、j同时向右移动,
		// 在实际匹配时,如果模式串i与字符串不匹配,那么会直接使得模式串索引i直接跳到前一条匹配的位置的下一位
		if pattern[i] == pattern[j] {
			next[i] = j + 1
			j++
			i++
		} else {
			// 当i、j不匹配时,若j不在字符串头,那么j回退到上一个匹配的位置
			// 若j在字符串头,i向右移动
			if j != 0 {
				j = next[j-1]
			} else {
				next[i] = 0
				i++
			}
		}
	}
	return next
}

字符串匹配

在获取到next数组之后,就直接获取到了如果不匹配情况下,模式串该如何走

func KMP(text, pattern string) bool {
	next := getNext(pattern)
	var i, j int
	for i < len(text) && j < len(pattern) {
		// 如果匹配,那么i、j同时向右移动
		if text[i] == pattern[j] {
			i++
			j++
			continue
		}
		// 如果不匹配,那么j回退到上一个匹配的位置
		if j != 0 {
			j = next[j-1]
		} else {
			i++
		}
	}

	return j == len(pattern)
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值