KMP算法中next数组、nextval数组的手工计算

刚接触数据结构,对于其中的一些算法都不是很了解,这几天刚在学习串的内容,里面介绍了两种串的模式匹配算法,一种是BF算法(也叫做BoyFriend算法);另一种是KMP算法(也叫做“看毛片”算法)。BF算法的实现很简单,很暴力,但是在时间复杂度的限制下,这不是一个很好的算法。为了提高程序运行的效率,出现了KMP算法,讲真的,算法真的很难理解(对于大佬来说,这种都是基础的题目,但对于像我样的菜鸡,就是登天啦~~)。这几天通过看视频教程,还有看大佬的博客,也懂的了一些简单的方法。

下面跟大家分享下成果吧~

例子:abaabcac
       

 

 12345678
例子abaabcac
next01122312

具体步骤:第一位和第二位肯定为0和1
          第三位开始比较前面串的最大真子串,没有为1
 第四位找:两位的时候 ab和ba 不一样
           一位的时候 a 和 a 一样,长度为1,所以next[4]=1+1=2
以此类推。
总结一下:第一位和第二位固定;
其余的位数就看它前面的串,找其中长度最大的真子串(注意:找的时候,找两端,头在一端,尾在一端,
        找到的串,从左到右读起来是相同的。比如:ab,ba这两个就不一样。相信聪明的你会一听就明白的),找到next的值为长度加1,未找到值为1。

 

nextval数组的计算方法呢,有两种:一种是靠直接观察法来算,另一种是依靠next数组来算。第一种没怎么懂,下面讲下用next数组来计算nextval数组的例子吧。
还是上面的例子:
例子:abaabcac

 

 12345678
例子abaabcac
next01122312
nextval01021302

具体步骤:若前两位相同,则nextval为0,若不同则为1,第二位的b与第一位的a不同,所以为1
 第三位的时候next值为1,第三位的a与当前next值所对应的值(即是第一位的a)相同,
          所以为0。
 第四位的next值为2,2对应的值为b,与当前的值不相同,nextval值为当前的next值,第四位为2
          第五位的next值为2,2对应的值为b,相同,继续比,第二位b对应的next值为1,1对应的next值
          为a,不同,结束,所以nextval值为1。
          以此类推,聪明的你肯定明白这其中的规律的。
总结下规律:第一位的nextval值肯定为0,第二位,观察第一位,相同为0,不同为1。剩下的求nextval:
若当前值与当前next所对应的值不同,则直接为当前next值;若相同,则继续查找对应的next值,有不同的就把对应的next值给nextval(正如上面的第五位查找),否则为0。
呼呼~说了这么多,你明白了吗?

下面贴上代码,供大家检验,对比。

#include<bits/stdc++.h>
using namespace std;
#define maxn 255
typedef struct
{
    char ch[maxn+1];
} SString;
void Init(SString &S)
{
    char str[maxn];
    cin>>str;
    S.ch[0] = strlen(str);//用第一个位置,存数组的长度
    for(int i=0;str[i];i++)
        S.ch[i+1] = str[i];
}
void get_nextval(SString &S1,int nextval[])
{
    int i=1,j=0;
    nextval[1] = 0;
    while(i<S1.ch[0])
    {
        if(j==0||S1.ch[i]==S1.ch[j])
        {
            i++;
            j++;
            if(S1.ch[i]!=S1.ch[j])nextval[i] = j;
            else
                nextval[i] = nextval[j];
        }
        else
            j = nextval[j];
    }
    for(int k=1; k<=S1.ch[0]; k++)
        cout<<nextval[k]<<' ';
}
void get_next(SString &T,int next[])
{
    int i=1,j=0;
    next[1] =0;
    while(i<T.ch[0])
    {
        if(j==0||(T.ch[i]==T.ch[j]))
        {
            ++i;++j;
            next[i]=j;
        }
        else
            j = next[j];
    }
     for(int k=1;k<=T.ch[0];k++)
        cout<<next[k]<<' ';
}

int main()
{
    SString S1;
    Init(S1);
    int next[maxn];
    ///Get_next(S1,next);
    get_next(S1,next);
    cout<<endl;
    get_nextval(S1,next);
}

欢迎大佬指教~

 

    原文作者:KMP算法
    原文地址: https://blog.csdn.net/yong_zi/article/details/78226418
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞