KMP算法实现

KMP算法——可运行版

最近在看KMP算法相关的知识,看到一篇非常不借的文章,让我在众多介绍KMP算法的博客中明白了这个算法的精髓。这个算法的思想,在这里,就不再陈述了,感兴趣的同学请参见这里

我在本篇文章中主要将文章中代码的问题改正使之能正确运行。代码如下:


#include <iostream>
using namespace std;

/*********************************
 *** get_next用来产生偏移量数组 ***
 ********************************/
void get_next(string t, int *next)
{
    int len = t.length();
    next[0] = -1;
    int k = -1;
    int j = 0;
    while (j < len - 1)
    {
        // p[k]表示前缀,p[j]表示后缀
        if (k == -1 || t[j] == t[k])
        {
            ++k;
            ++j;
            next[j] = k;
        }
        else
        {
            k = next[k]; // 找到之前一次更小的匹配
        }
    }
}

/***************************************
 * Optimized get_next function
 ***************************************/
void get_nextval(string t, int *nextval)
{
    int len = t.length();
    nextval[0] = -1;
    int j = 0;
    int k = -1;
    while (j < len - 1)
    {
        if (k == -1 || t[j] == t[k])
        {
            ++k;
            ++j;
            if (t[j] != t[k])
            {
                nextval[j] = k;
            }
            else
            {
                nextval[j] = nextval[k];
            }
        }
        else
        {
            k = nextval[k];
        }
    }
}

/*********************************
 * kmp_search用来从s中找出第一次
 * 匹配t成功的index(从0开始)
 ********************************/
int kmp_search(string s, string t)
{
    int i = 0;
    int j = 0;
    int slen = s.length();
    int tlen = t.length();
    int *next = new int[tlen];
    //get_next(t, next);
    get_nextval(t, next);
    while (i < slen && j < tlen)
    {
        // 如果j==-1
        if (j == -1)
        {
            i++;
            j++;
        }
        else if (slen - i >= tlen - j)// 注意这里与原文代码不同
        {
            if (s[i] == t[j])
            { // 当前字符匹配成功时
                i++;
                j++;
            }
            else
            {
                j = next[j];
            }
        }
        else
            break;
    }
    if (j > 0 && j == tlen) // j>0表示不是空串
        return i - j;
    else
        return -1; // 未匹配成功
}

int main()
{
    cout << kmp_search("", "") << endl;
    cout << kmp_search("bbc abcdab abcdabdcabde", "abcdabd") << endl;
    return 0;
}

注意:在kmp_search中,原文中代码是 if  (j == -1 || s[i] == p[j]),而这样是不对的,因为或条件的第二个条件必须在slen-i比tlen-j大的条件下成立才可对,否则不管比较结果如何都会匹配失败。



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KMP算法(Knuth-Morris-Pratt算法)是一种字符串匹配算法,用于在一个主串中查找一个模式串的出现位置。下面是KMP算法实现示例(使用C语言): ```c #include <stdio.h> #include <string.h> void computeLPSArray(char* pattern, int pattern_length, int* lps) { int len = 0; lps[0] = 0; // lps[0]总是0 int i = 1; while (i < pattern_length) { if (pattern[i] == pattern[len]) { len++; lps[i] = len; i++; } else { if (len != 0) { len = lps[len - 1]; } else { lps[i] = 0; i++; } } } } void KMP(char* text, char* pattern) { int text_length = strlen(text); int pattern_length = strlen(pattern); // 创建并初始化lps数组 int* lps = (int*)malloc(sizeof(int) * pattern_length); computeLPSArray(pattern, pattern_length, lps); int i = 0; // text中的索引 int j = 0; // pattern中的索引 while (i < text_length) { if (pattern[j] == text[i]) { j++; i++; } if (j == pattern_length) { printf("Pattern found at index %d\n", i - j); j = lps[j - 1]; } else if (i < text_length && pattern[j] != text[i]) { if (j != 0) { j = lps[j - 1]; } else { i++; } } } free(lps); } int main() { char text[] = "ABABDABACDABABCABAB"; char pattern[] = "ABABCABAB"; KMP(text, pattern); return 0; } ``` 这是一个简单的KMP算法实现,可以在给定的文本中查找指定的模式串。当找到匹配时,会输出模式串在文本中的起始索引。 注意,在使用这段代码时,需要包含`<stdio.h>`和`<string.h>`头文件,并在编译时链接数学库(例如,使用`-lm`选项)。 希望这个示例能对你有所帮助!如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值