KMP算法以及其核心next数组


/*
    KMP算法核心之next数组
    设字符串数组为ch[n],对应的next数组为next[n]
    1、则必有next[0]=-1(此时数组ch和next的开始下标都为0)或者
             next[1]=0(此时数组ch和next的开始下标都为0)
    以及next[2]=1;
    2、当i>=2时,判断ch[i]和ch[j]是否相等,
        1)若相等,则有next[++i] = ++j;
        2)若不相等,则j=next[j],然后重新开始ch[i]和ch[j]的匹配
    整个算法过程中一定有i>=j
    算法实现如下:(综合考虑了王道数据结构(P266)和天勤数据结构(P99))
*/

void get_next(char T[], int next[])
{
    int i = 1, j = 0;   //或者 int i = 0 ,j = -1 ;
    next[1] = 0;       //或者next[0]=-1
    while (i < T[0])   //T[0]中保存的是数组T[]的长度
    {
        if (0 == j || T[i] == T[j])
        {
            next[++i] = ++j;
        }
        else
        {
            j = next[j];/*j只会取大于等于0的数,不用担心j=next[0]=-1的情况,因为j=0根本就不
                        会进入else语句中,进入else语句中的一定是 j>0 的情况*/
        }
    }
}

/************************************************************************/
/*KMP算法实现核心:主串只会向右移动,模式串才有可能回溯,
    KMP算法在形式上与简单的模式串匹配算法很相似,不同之处在于仅仅当匹配过程中产生失配时,主串的i指针不变
    ,模式串的j指针退回到next[j]的位置,然后重新开始匹配主串i指针和模式串j指针。若还是产生失配,j指针继续
    回退,直到主串i指针和模式串j指针匹配或者j==0。当主串i指针和模式串j指针匹配时或者j指针为0时,next[++i]
    =j++,表示的是应该从主串的第i+1个位置开始匹配了(j=0时,表示的是主串的第i个位置和模式串的第一个字符都不
    相等了,所以应该从主串的第i+1个位置开始匹配了)
上代码*/
/************************************************************************/

int KMP(char S[], char T[], int next[],int pos )    // T为模式串,S为主串,next数组为模式串S的next数组
                                                    //pos 表示从主串的第pos个字符之后的位置开始进行匹配
{
    int i = pos, j = 1;
    while (i <= S[0] && j <= T[0]) // 和next数组处一样,S[0]保存的是主串的长度,T[0]保存的是模式串的长度
    {
        if (0 == j || S[i] == T[j])    //主串i指针处和模式串j指针处匹配或者模式串j指针回溯到0,无法继续回溯了
                                    //则应当匹配主串的第i+1指针处和模式串的第j+1指针处
        {
            ++i;
            ++j;
        }
        else
        {
            j = next[j];        //匹配失效,模式S串回溯
        }    
    }
    if (j > T[0])
    
        return i - T[0];        //返回主串第pos位置之后的串和模式串总共匹配的长度
    else
        return 0;
    
}

猜你喜欢

转载自blog.csdn.net/qq_15054345/article/details/84000805
今日推荐