数据结构学习思考:KMP算法求解next数组

一、算法解析

这是2022版王道书数据结构第110页上的KMP算法求解next数组算法,书中没有详细说明原理,且咸鱼学长也说这是整个课程中比较晦涩的算法之一,引发了笔者的思考。

void get_next(String T,int next[]){
    int i=1, j=0;
    next[1]=0;
    while(i<T.length){
        if(j==0||ch[i]==T.ch[j]){
            ++i; ++j;
            next[i]=j;  //若pi=pj,则next[j+1]=next[j]+1
        }
        else
            j=next[j];  //否则令j=next[j],循环继续
    }
}

求解原理:

1、先检查待求字符 Z 之前 Y 字符的最大匹配长度为 m 个字符,对应为起始的 T[1]-T[m] ,此时若 X(T[m+1])==Y ,则可以判断 Z 之前的最大匹配字符为 m+1 个,故next为 m+2

2、若 X!=Y ,则需要查找一个①串与②串相匹配,同时由于 X 前的最大匹配字串为 n 个,故②串==③串,同时①串==③串,找到与①串相匹配的②串,此时若 ξ==Y,则 Z 的 next[Z]=n+1

对应上述代码中的while循环

    while(i<T.length){
        if(j==0||ch[i]==T.ch[j]){
            ++i; ++j;
            next[i]=j;  //若pi=pj,则next[j+1]=next[j]+1
        }
        else
            j=next[j]  //否则令j=next[j],循环继续
    }

二、KMP模板

 模板中 i=0 与 j=-1 是因为程序中字符串是从下标0开始的,而王道讲解是默认第一个字符下标为1

void get_next(string T, int next[]) { 
    memset(next, 0, sizeof(next)); //多组输入时,每次需要初始化next[]数组
    int i = 0, j = -1;
    next[0] = -1;
    while (i < T.length()){
        if (j == -1 || T[i] == T[j]) {
            ++i; ++j;
            next[i] = j;  //若pi=pj,则next[j+1]=next[j]+1
        }
        else
            j = next[j];  //否则令j=next[j],循环继续
    }
}

int Index_KMP(string S, string T, int next[]) //S是字符串,T是模式串
{
	int i = 0, j = 0;
	while (i < S.length() && j < T.length()){
		if (j == -1 || S[i] == T[j]){
			++i; ++j;
		} 
		else
			j = next[j];

		if (j == T.length()) //匹配成功
			return i - T.length();
		else //匹配失败
			return 0;
	}
}

要注意的是,Index_KMP()函数是针对求得模式串匹配索引的函数,若题意要求求字符串内匹配子串的个数时,while循环中的 j < T.length() 需要删去,其中的内容要根据实际情况调整。

另外,get_next()函数可以优化成get_nextval()函数,可以加快字符串的匹配速度,算法细节见2022版王道教材 P111页 4.2.3KMP算法的进一步优化

void get_nextval(string T, int nextval[]) {
    memset(next, 0, sizeof(next)); //多组输入时,每次需要初始化next[]数组
	int i = 0, j = -1;
	nextval[0] = -1;
	while (i < T.length()) {
		if (j == -1 || T[i] == T[j]) {
			++i; ++j;
			if (T[i] != T[j]) nextval[i] = j;
			else nextval[i] = nextval[j];
		}
		else
			j = nextval[j];
	}
}

猜你喜欢

转载自blog.csdn.net/qq_21891843/article/details/123871649