2

KMP的next[]数组的求解是kmp算法的最重要的一步.下面我们来介绍它.

void GetNext(char* p, int next[]) 
{
    int pLen = strlen(p); //求出长度;
    next[0] = -1; 
    int k = -1;
    int j = 0;
    while (j < pLen - 1)
    {
        //p[k]表示前缀,p[j]表示后缀
        //k=-1是对防止形成死循环;
        if (k == -1 || p[j] == p[k])   //匹配时,
        { 
            ++k;
            ++j;
            next[j] = k;
        }
        else  //不匹配时;
        {
            k = next[k]; // 储存当前置
        }
    } 
 }

原理对每一种的可能的匹配的情况进行枚举存储与next[]数组中;
举个栗子:ababaa;
可能在 a ,ab ,aba,ababa, 情况停下来next[]算在这些串中的下一次开始位置.
比如aba就从b位置开始匹配;


完整的程序

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

// MYSELEF KMP 算法;
void Getnext(char *p, int next[])
{
    int Plen = strlen(p);
    next[0] = -1;
    int k = -1;
    int j = 0;
    while (j < Plen)
    {
        if (k == -1 || p[k] == p[j])
        {
            ++k;
            j++;
            next[j] = k;
        }
        else
            k = next[k];
    //    printf("%d %d", j, k);
    }
}
int my_kmp(char  *T, char *p, int next[])
{
    int j=0, d=0;
    while (j < strlen(T) && d < strlen(p))
    {
        // d=-1 防止在 首位不相等和,的情况下的死循环;
        if (d = -1 || T[j] == p[d]){ //匹配了才加的;
            d++;
            j++;
        }
        else
            d = next[d] ;//,利用相同的真前缀和真后缀对子串进行调整;
    }
if (j > strlen(p)) {
    return  j - strlen(p); //返回位号;
}
else 
return 0;
}
int main()
{
    char T[100];
    char  S[100];
    int Next[100], n;
    gets(T);  //主串;
    gets(S);  //子串

    Getnext(S, Next);
    n = my_kmp(T, S, Next);
    printf("%d", n);

}

举个栗子;
T : abcabcb
s : abcb;
Getnext(s);
next[]={-1 , 0 ,0 ,0,-1} //代表在不匹配时的下一次字串该从哪里开始;
n=my_kmp(T,p,next);

第一轮: abc 匹配;j=3
       取出next[3]=0;
       所以下一次的从S[0]开始和匹配在此过程种j不变,因为在abc中bc 都与a不同;
       接下来相似;
   

XXXXaXXX
XXXXb
在a处失配时;x 为相同的真前缀和真后缀 ,即从X的后一位开始于a比较;


黑白
144 声望0 粉丝