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]中,并设置jnext[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函数中,应尽量优化循环条件和逻辑判断流程。

通过以上优化,代码不仅易于理解和维护,还可以更好地满足实际应用场景的需求。

上一篇:Java学习笔记:装箱,拆箱,字符串转化为其他类型 以及 其他类型转化为字符串
下一篇:Java学习笔记:数组

发表评论

最新留言

表示我来过!
[***.240.166.169]2025年04月26日 13时37分17秒

关于作者

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

推荐文章