
KMP和BF模式匹配算法
发布日期:2021-05-18 06:48:08
浏览次数:16
分类:精选文章
本文共 2751 字,大约阅读时间需要 9 分钟。
这里展示了一个实现字符串匹配算法(KMP算法和BF算法)的C语言代码,代码之外我们还会对其中的功能进行简单的解读和分析。
1. KMP算法(Knuth-Morris-Pratt算法)
KMP算法是一种高效的字符串匹配算法,尤其适用于多次模式匹配场景。其核心思想是利用预处理(预处理)步骤构建一个“子串接下标”,从而在主串扫描时避免重复匹配,从而显著提升匹配效率。
KMP算法的实现代码分析
void get_next(sString* T, int* next) { int i = 1, j = 0; next[1] = 0; while (i < T[0]) { if (j == 0 || T[i] == T[j]) { j++; i++; if (T[i] != T[j]) { next[i] = j; } else { next[i] = next[j]; } } else { j = next[j]; } }}
预处理阶段(
通过遍历整体子串get_next
函数):T
,构建一个next
数组,记录每个位置i
的匹配信息 (j
值)。当出现第一个不完全匹配时,记录当前匹配的长度,并根据前缀的最大匹配长度更新后续位置的匹配信息。- 如果
T[i] == T[j]
且j == 0
(起始位置),则j
加1并继续匹配。 - 如果
T[i] != T[j]
,则记录当前j
的值到next[i]
中,并设置j
为next[j]
来重新继续匹配。 - 如果
T[i] == T[j]
且j != 0
,则根据子串起始位置的next[j]
来设置当前的next[i]
。
- 如果
匹配阶段(
扫描主串Index_KMP
函数):S
,从指定位置pos
开始,利用预处理好的next
数组实时查找子串T
。- 遍历
S
中的字符,并根据next
数组中的信息调整匹配位置j
,直到完整匹配子串T
或达到主串末尾。 - 如果
j > T[0]
,表示子串已在主串中找到匹配位置,返回匹配位置。 - 否则,表示主串扫描完毕,但未找到匹配位置,返回-1。
- 遍历
2. BF算法(Boyer-Moore算法)
BF算法(也称为Boyer-Moore算法)是一种简单有效的字符串匹配算法,常用于记录一次匹配。其核心思想是记录不匹配的位置,并在主串扫描中跳过这些不匹配的位置,提升效率。
BF算法的实现代码分析
int Index_BF(sString* S, sString* T, int pos) { int j = 1; int i = pos; int k = i; while (k <= S[0] - T[0] + 1) { while (j <= T[0] && S[i] == T[j]) { i++; j++; } if (j > T[0]) { return i - T[0]; } else { k = i; j = 1; } } return -1;}
- BF算法的匹配逻辑:
- 跟踪当前位置
i
(主串S
的位置)和j
(子串T
的位置)。 - 当
S[i] == T[j]
且j
未达到子串长度时,j
加1,i
加1。 - 一旦匹配失败(
S[i] != T[j]
),则跳出循环,重新从k = i
(下一个未检查的位置)和j = 1
开始继续匹配。 - 如果在某一次完整匹配中
j > T[0]
,表示子串已完全匹配,返回匹配位置。 - 否则,返回-1,表示未找到匹配。
- 跟踪当前位置
3. 两种算法的比较
参数 | KMP算法 | BF算法 |
---|---|---|
时间复杂度 | O(n + m) | O(nm) |
空间复杂度 | O(m) | O(m) |
适用场景 | 需要预处理,且查询频繁 | �ARAM匹配次数较少 |
- KMP算法优点:
- 预处理时间较低,适合多次查询。
- 构建
next
数组的复杂度为O(m)。 - 主串扫描的时间为O(n),匹配效率较高。
- BF算法优点:-实现简单,适合只需一次匹配的场景。
- 如果词 prodects 多次不匹配,会增加查找效率。
4. 代码主函数部分
int main() { sString S[20]; sString T[20]; int pos; int n; pos_BF = Index_BF(S, T, pos); pos_KMP = Index_KMP(S, T, pos); if (pos_BF == -1) { printf("匹配失败!\n"); } else { printf("匹配位置结果为 position = %d\n", pos_BF); printf("匹配成功!\n"); } if (n == 2) { // KMP模式匹配的具体实现与BF类似,不同处于于算法实现细节 pos_KMP = Index_KMP(S, T, pos); if (pos_KMP == -1) { printf("匹配失败!\n"); } else { printf("匹配位置结果为 position = %d\n", pos_KMP); printf("匹配成功!\n"); } } else { printf("error data!!!\n"); }}
- 代码逻辑解读:
- 根据用户选择的模式(BF或KMP),调用对应的匹配函数进行处理。
- 根据函数返回的位置判断是否匹配成功,并输出相应信息。
- 当输入错误或模式选择错误时,输出“error data!!!”提示。
5. 技术注意事项
待优化点:
- 当子串长度超过主串长度时,直接返回-1。
- 可同时输出子串匹配的具体位置信息。
- 对异常情况(如空字符串、不匹配子串)做好判断处理。
实现细节:
sString
类型设定需与实际字符串长度对应。- 要确保字符串输入的有效性,避免缓冲区溢出或其他安全问题。
- 在
get_next
函数中,应尽量优化循环条件和逻辑判断流程。
通过以上优化,代码不仅易于理解和维护,还可以更好地满足实际应用场景的需求。
发表评论
最新留言
表示我来过!
[***.240.166.169]2025年04月26日 13时37分17秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!