字符串匹配之BF算法和KMP算法(看不懂算我输),j = next(j)的原理

网上关于这个算法,五花八门,看得我是眼花瞭乱,脑抽筋,都说包会,可能是我确实脑细胞不够用,各种版本看了一整天,通过自己的理解和实践,总结出我这种小白都能理解的方法来,以供我以后忘记了,还能通过看一遍就能理解

首先先来一断BF暴力穷举法:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char Primary[100] = "abcdabccabcbabca";
    char secondary[20] = "abcb";
    int i = 0;
    int j = 0;
    while(i <= strlen(Primary)-1 && j <= strlen(secondary)-1)
    {
        if(Primary[i] == secondary[j])
        {
            i++;
            j++;
        }
        else
        {
            i = i-j+1;
            j = 0;
        }

    }
    if(j > strlen(secondary)-1)
    {
        printf("匹配成功,子串在主串的%d位置",i-strlen(secondary));
    }
    else
    {
        printf("匹配失败!");
    }
    return 0;
}


这个就不用我去多说了,网上太多

至于KMP算法,我这里也只讲一个关键难懂的地方,那就是j = next(j)的原理,别的相信大家看了那么多的版本,都已经知道了.先来一段完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void get_next(char* model, int* next)
{
    int i = 0;
    int j = -1;
    next[0] = -1;
    while(i < strlen(model) - 1)
    {
        if(j == -1 || model[i] == model[j])
        {
            i++;
            j++;
            next[i] = j;
        }
        else
        {
            j = next[j];
        }
    }
}
void match_string(char* Primary, char* secondary, int* next)
{
    int i = 0;
    int j = 0;
    while(i <= (strlen(Primary)-1) && j <= (strlen(secondary)-1))
    {
        if(Primary[i] == secondary[j])
        {
            i++;
            j++;
        }
        else
        {
            j = next[j];
        }
        if(j == -1)
        {
            i++;
            j = 0;
        }

    }
    if(j > strlen(secondary)-1)
    {
        printf("匹配成功,子串在主串的%d位置",i-strlen(secondary));
    }
    else
    {
        printf("匹配失败!");
    }
}
int main()
{
    int next[20] = {0};
    char Primary[100] = "abcabadababfabc";
    char secondary[20] = "abadababf";
    get_next(secondary,next);
    match_string(Primary, secondary, next);
    return 0;
}

针对上面这个模式串"abadababf",现在我们来讲讲j = next(j):

此时,P[j] != P[i],怎么办,怎-么-办?

我们都知道,要想求next[f]的值,得知道next[b]的值,而且按上面的情况来说b要等于d,才行.问题现实是残酷的,b != d.现在next[b] = 3,既然next[b]=3时,b != d,计算机就在想,取最长的相同前后辍不行,我就取第二长的,必须得保证在前后辍相同的规则下,找到一个和b相同的数,那么问题来了,第二长的是谁,前辍a   ab (aba不能用了,就和前面情况一样),后辍是a ba.  等等,等等....前辍a   ab,后辍是a ba.,让我捊一捊,这不就是求next[j]吗?求出相同前后辍a,那么现在next[b]的值是1了,这里要说明一下,求出来的这个值,不影响实际next[b] = 3的值,求这个值只是做为中间值来最后求next[f]的值.

现在next[b]暂时为1,那么为1时,前面有说过,还有一个条件,把下标为1的值移过去看相不相等.

 有没有这么巧,这么就相等了,如果这样,next[f]的值不就是1+1 = 2了,好像就是这么回事,网上的各种说法到这里就结束了,那我这里不行,我就是要杠啊,如果第7位,不是b,而是a,那情况会是怎么样呢?

如果是这样的话,next[b] = 1的情况也被否决了,因为b != a,那么计算机就在想,大不了我再找下一个相同的前后辍啊,啪!再来一个j = next[j]  现在好了,j变成零了,情况又变了:

 我想说,我不是故意的啊,这么巧,竟然相等了,那好吧,这时next[f] = 0+1,正所谓无巧不成书啊,但我就是不信邪,如果P[7],不是b,也不是a,是e,我看你怎么办吧,(计算机想,大不了我再j = next[j]一次,有什么大不了的,这时j = -1,什么情况,我前面收到的指令好像说j = -1,是说不和你玩了,我主串加1再说,然后j也归零,这时next[f] = 0

说了这么多,相信小伙伴们对j = next[j]的逻辑有一定的了解了, 也知道为什么P[j] != P[i]时,要用j = next[j]了吧.......

什么?还没有懂?来吧,再给你最后一次机会!!

 前面说了,找P[7],b的第二长的前后辍,后辍有a,ba.先打住,当i和j在这个位置,是不是说明了P[0~j-1] = P[i-3~ i-1],既然如此b的后辍,下标6,和下标56,就等于下标2,和下标12,这样还不能说明就是next[j]吗?

所以这里j = next[j]不是网上说的简单的回溯,而是尽可能的在找相同的前后辍,直到找不到为止,如果实在没有找到主串就要+1,模式串就归零了.

如果觉得对你有帮助的小伙伴,点个赞

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值