本文共 2224 字,大约阅读时间需要 7 分钟。
KMP(Knuth-Morris-Pratt)算法是一种高效的字符串匹配算法,广泛应用于文本搜索、数据处理等领域。其核心思想在于利用前缀和后缀的最长公共部分(LPS,Longest Prefix Suffix)来优化匹配过程,从而减少不必要的比较操作,提高效率。
next 数组用于记录每个位置发生不匹配时,应该回溯到的位置。具体来说,next[i] 表示在目标串的第 i 个字符发生不匹配时,应该将 j(目标串的当前匹配指针)跳转到的位置,继续与主串进行比较。
next 数组的计算分为以下几个步骤:
初始化:首先,next 数组的第一个元素被初始化为 -1,这表示当目标串的第一个字符发生不匹配时,应该将 j 设为 -1,开始从下一个字符开始匹配。
遍历目标串:从左到右遍历目标串的每个字符,维护两个指针 j 和 k:
更新前缀长度:如果当前字符与前缀字符匹配,则 k 增加 1。
处理不匹配情况:如果当前字符与主串的字符不匹配,则将 k 设为 next[k],并继续比较。
通过上述步骤,可以逐步构建出 next 数组,使得在匹配过程中能够高效地跳转到最近的有效位置,减少不必要的比较。
KMP 算法的代码实现主要包含两个部分:
以下是 KMP 算法的伪代码:
function KMP(str_main, str_target) // 1. 初始化 next 数组 n = length(str_target) next = array of size n, initialized to 0 k = 0 for i from 0 to n-1: while k > 0 and str_target[k] != str_main[i]: k = next[k] if str_target[k] == str_main[i]: k += 1 next[i] = k k = next[i] // 2. 主循环进行匹配 i = 0 // 指针,遍历主串 j = 0 // 指针,遍历目标串 while i < length(str_main) and j < length(str_target): if str_main[i] == str_target[j]: i += 1 j += 1 else: j = next[j] if j == length(str_target): return i - j // 返回匹配的位置 else: return -1 // 未找到
为了更好地理解 next 数组的计算过程,我们可以通过一个具体的例子来分析:
假设目标串为 ABABCABAB,主串也为 ABABCABAB。
A 和 A,相等,k 增加到 1,next[0] = 1。B 和 B,相等,k 增加到 2,next[1] = 2。A 和 C,不相等,k = next[2] = 0,比较 A 和 A,相等,k 增加到 1,next[2] = 1。B 和 B,相等,k 增加到 2,next[3] = 2。C 和 C,相等,k 增加到 3,next[4] = 3。A 和 A,相等,k 增加到 4,next[5] = 4。B 和 B,相等,k 增加到 5,next[6] = 5。C 和 C,相等,k 增加到 6,next[7] = 6。最终,next 数组为:[1, 2, 1, 2, 3, 4, 5, 6]。
通过 next 数组,KMP 算法在匹配过程中能够快速跳转到最近的有效位置,避免了暴力搜索中的大量不必要比较。例如,在主串和目标串不匹配时,j 会跳转到 next[j],并继续比较,而不是从头开始重新匹配。
KMP 算法通过预处理目标串,构建 next 数组,实现了高效的字符串匹配。其核心思想是利用前缀和后缀的最长公共部分来减少回溯次数,从而降低了时间复杂度,提高了匹配效率。理解 next 数组的计算过程和逻辑是掌握 KMP 算法的关键,通过多练习和分析,可以更深入地掌握这一高效的算法。
转载地址:http://mjsi.baihongyu.com/