KMP算法

        KMP 算法(Knuth-Morris-Pratt 算法)是一个著名的字符串匹配算法,对于字符串的匹配效率很高,只是理解有些复杂。

        对于朴素的字符串算法来说,我们可以循环遍历所有的字符进行挨个比较,但发生所需匹配的字符串的某个位置的元素不同时,我们就需要重新从头开始匹配,直到所需匹配的字符串位置指向'\0',耗费的时间多,效率低。

int search(string source, string target) {
    int s = source.length();
    int t = target.length();
    int index = -1;
    for (int i = 0; i < s - t; i++) {
        int j;
        for (j = 0; j < t; j++) {
            if (source[i + j] != target[j])
                break;
        }
        if (j == t) {
            index = i;
            break;
        }
    }
    return index;
}

        我们将这一指针返回初始位置的现象称为指针回溯,但是若所需匹配的字符串前面已经有部分重复的成功匹配,我们是否可以将指针进行更小值的前跳,降低所需的匹配次数。

        如上所示,当 i 出现不匹配时,将所需匹配的字符串的指针位置改成4,其中前四个元素与上面所需匹配的字符串是已经匹配成功的了,我们只需考虑在 i 的位置上是否是 字符 'a',若是,则继续匹配,若不是,则进行相同的操作,将元素指针继续向前移,如下所示。

        KMP算法通过减少回溯的次数字符串匹配的效率。


#include <iostream>
#include<string>
int* getNext(string source)
{
    int* next = new int[source.length()];
    next[0] = -1;  //当前下标之前最大重复字符串长度
    int index = 0;  // 字符串下标
    int j = -1;  //重复元素字符串长度
    while (index < (int)source.length() - 1)
    {
        if (j == -1 || source[index] == source[j])  //当index的元素与当前j的元素相同时,重复的元素串长度加1, i++,j++
        {
            index++;  //下标++
            j++;  //重复字符串长度++
            next[index] = j; //赋值
        }
        else
        {
            j = next[j]; //取当前字符串开头重复长度位置后一位,判断是否相同
        }
    }
    return next;
}

int KMP(string Source, string target)
{
    int i = 0;
    int j = 0;
    int* next = getNext(Source);
    while (i < (int)Source.length() && j < (int)target.length())
    {
        if (j == -1 || Source[i] == target[j])
        {
            i++;
            j++;
        }
        else
        {
            j = next[j];
        }
    }
    delete next;
    if (j == (int)target.length())
    {
        return i - j; //返回所匹配结束位置的初始位置
    }
    return -1;
}

int main()
{   
    string S="ffffffffffffhassfhslkfhsoifwpf", T="fhso";
    int i = KMP(S, T);
    cout << i;
}

        通过该方法得到的输出结果:

         该方法主要用于当字符串内部重复过多时,一般还是多使用朴素匹配算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值