KMP串匹配算法原理及实现

本文深入探讨了KMP字符串搜索算法的原理及其优化过程,并提供了详细的代码实现。通过对比错误实现与正确实现,帮助读者理解KMP算法的核心思想。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一图胜千言


代码:
int KMPGetNext(const char* pc_str, int n)
{
        const int STR_LEN = (NULL == pc_str) ? /
                                    -1 : (int)strlen(pc_str);
        const int END = n - 1;
        int ret = 0;
        int max_len = 0;
        if ((NULL == pc_str) || (n < 1)) {
                ret = -1;
                goto END;
        }
        if (END >STR_LEN) {
                ret = -1;
                goto END;
        }
        for (max_len = END - 1; max_len >= 0; --max_len) {
            int i = max_len, j = END;
            while ((i >= 0) && (pc_str[i--] == pc_str[j--])) {
            }
            if (i < 0) {
                    ret = max_len;
                    goto END;
            }
        }
END:
        return ret;
}
int KMP(const char* pc_str, const char* pc_sub)
{
        const int STR_LEN = (NULL == pc_str) ? /
                                    -1 : (int)strlen(pc_str);
        const int SUB_LEN = (NULL == pc_sub) ? /
                                    -1 : (int)strlen(pc_sub);
        int ret = 0;
        int i = 0, j = 0;
        if ((NULL == pc_str) || (NULL == pc_sub)) {
                ret = -1;
                goto END;
        }
        if (STR_LEN < SUB_LEN) {
                ret = -1;
                goto END;
        }
        for (i = 0, j = 0; /
             (i < STR_LEN) && (j < SUB_LEN); /
             ++i, ++j) {
                 if ((STR_LEN - i) < (SUB_LEN - j)) {
                        ret = -1;
                        break;
                 }
                 if (pc_str[ i ] != pc_sub[j]) {
                        j = KMPGetNext(pc_sub, j);
                        if (j > 0) {
                                --i;
                        }
                 }
        }
        if (SUB_LEN == j) {
                ret = i - SUB_LEN;
        }
END:
        return ret;
}



上面的实现是错误的,现追加
static
void __gen_next__(char const *str,
                  intptr_t n,
                  intptr_t *next,
                  intptr_t m)
{
    intptr_t i = 0;
    intptr_t j = 1;

    assert(m >= n);

    next[i] = -1;
    next[j] = 0;
    while (j < n - 1) {
        if ((str[i] == str[j])) {
            next[j + 1] = i + 1;
            ++i;
            ++j;
        } else {
            i = next[i];
            if (-1 == i) {
                i = 0;
                next[++j] = 0;
            }
        }
    }
}



intptr_t kmp(const char* text, const char* pattern)
{
    intptr_t rslt;
    intptr_t text_len = strlen(text);
    intptr_t pattern_len = strlen(pattern);
    intptr_t *next = (intptr_t *)calloc(pattern_len, sizeof(intptr_t));

    memset(next, 0, pattern_len);

    __gen_next__(pattern, pattern_len, next, pattern_len);
#if 0
    for (intptr_t i = 0; i < pattern_len; ++i) {
        fprintf(stderr, "%ld: %ld\n", i, next[i]);
    }
#endif

    // do kmp
    do {
        intptr_t i = 0;
        intptr_t j = 0;

        while ((i < text_len) && (j < pattern_len)) {
            if ((-1 == j) || (text[i] == pattern[j])) {
                ++i;
                ++j;
            } else {
                j = next[j];
            }
        }

        if (j >= pattern_len) {
            rslt = i - pattern_len;
        } else {
            rslt = -1;
        }
    } while (0);

    free(next);

    return rslt;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值