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大的条件下成立才可对,否则不管比较结果如何都会匹配失败。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值