kmp算法分析

理解关键:

                1.时间复杂度o(m+n),主串不回溯,一直向前推进。模式串通过next[]表进行下标跳转

                2.模式串next[]数组构造。

                求解当前下标i的next[i]的关键是找出p[0]到p[i-1]字符串中,以p[i-1]结尾的最长子串,该子串满足条件p[0]~p[k-1]与p[i-k]~p[i-1]相同(即查找0~i-1的最长相同前后缀),则next[i] = k;

                next表构造代码如下:
 

#define MAX_PATTERN_LEN 20
int next[MAX_PATTERN_LEN] = { 0 };
int makeNext(char* p)
{
    next[0] = -1; next[1] = 0;
    int i, k;
    for (i = 1, k = 0; i < strlen(p);)
    {
        while (p[i] != p[k] && (k >= 0))
        {
            k = next[k];
        }
        i++;
        k++;
        next[i] = k;
    }

    printf("the next table:\n");
    for (i = 0; i < strlen(p); i++)
    {
        printf("%c %d\n", p[i], next[i]);
    }

    return 0;
}

      该算法最难理解的就是next[]数组回溯时,为什么是k=next[k], 而不是k=k-1这样挨着回溯:

       回到算法的关键是找到模式串p[0]~p[i-1]子串的最长相同前后缀,而next[]表正是存储的0~i-1每个下标位置的相同前后缀,所以最长相同前后缀的值一定是next[]表中存储的值。

      下面来通过图解来清晰的理解:

       其中k = next[j], 则A,B,C都是有相同前(即以p[0]位头,以p[j-1]为尾)后缀的字符段,且长度逐减。

       当j位置失配时,说明0 ~ j-1是匹配成功的,目标串不移动,如果目标串text的当前下标为i,则text[i-1]与模式串的p[j-1]匹配,问题就是要使模式串进行最小的移动, 即需要找到已经匹配成功的0 ~ j-1的字符串中以p[0]位头,以p[j-1]为尾的前缀,而满足该条件的0 ~ k -1, 0 ~ next[k] -1, 0 ~ next[next[k] - 1]......, 所以最长的就是0 ~ k-1(即红色的A1段), 即next[j] - 1。次长的就是0 ~ next[k]-1(即绿色的B1段), 以此类推,得出算法回溯时为什么k要递归的等于next[k]了, 即k = next[k]

          本人菜鸟,该问题困扰我很久,花了很多时间来理解这个,网上的讲解看了很多,总感觉有点似懂非懂,现在终于感觉搞明白透彻了,按照自己的理解记录下来。如果有小伙伴也跟我一样看了很多还是不懂,希望我这篇能帮到你

       参见链接:https://www.cnblogs.com/tangzhengyue/p/4315393.html

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值