kmp算法的实现

void getvoid GetNext(int next[],int length,char *s){

1
<em> </em>
void GetNext(char*s,int length,int next[])
{
    next[0]=0;
    int i=1,j=0;
1
<em>//首先我们初始化j等于零,其中,j表示的是模式串前缀的最后一个数的下标志,同时也表示前后缀相同的最大值,j表好似的是后缀的最后一个下标所指的位置</em>
    for(i=1;i<length;i++){
        while(j>0 && s[i]!=s[j]){
            j=next[j-1];      //当其不相等的时候,用while循环回溯
        }
        if(s[i]==s[j])       //相等的时候j向前加
        {
            j++;
        }
        next[i]=j;        //更新next数组,,主义,这里使用next[i]=j
    }
}
    
int strStr(char* haystack, char* needle) {
    int numssize1=strlen(haystack);
    int numssize2=strlen(needle);//先得到模式串和目标川的长度
    
    if(numssize2==0){
        return 0;//若模式串的长度为零,返回零,符合c语言中的定义???
    }
    int next[numssize2];
    int j=0,i=0;
    GetNext(needle,numssize2, next);//初始化next数组
    for(i=0;i<numssize1;i++)
    {
        while(j>0 && haystack[i]!=needle[j]){   //此时的i和j和上文的i,j表示的意思不同,初学者常犯的错误(当然也包括我)
            j=next[j-1];                                  //若匹配不成功 则回溯,正是在这一步简化了运算,为何,因为既然数组下标能够加到j,说明其前面的几个数必然已经和目标串的前j个字符
                                                              //匹配成功了,那么这时i不动,我们只需要在比较第needle[next[j-1]+1]和haystack[i]即可,换句话说,
                                                              //此时重置了匹配进程,haystack中只有前next[j-1]个数被用到了,而不是向之前一样j个都被用到了,
                                                             //相反,此时若匹配失败的话,将会因为while循环不断回溯,一直到0时,将会(注意此时,j任然指向needle)
        }
        if(haystack[i]==needle[j]){
            j++;                                         //此时如匹配成功,j++
        }
        if(j==numssize2)                      //说明历经考研之后,j成功来到了了末尾,注意!此时j在最后一次时为j-1,相等后+1,即此时next[j]已经越界了,知识我们没有使用而已,此后如要
        return (i-numssize2+1);              //重新使用的话,还是得小心
                                                          //此时i已经指到对应位置+numssize的地方,又根据题意要求,我们加上1
    }
    return -1;                                   //若经历了所有遍历后,函数没有在上一个出口返回,说明没有目标川中没有与模式串匹配的地方,那么,返回-1
}

  

posted @ 2022-02-17 11:07  红石Hong  阅读(33)  评论(0)    收藏  举报