データ構造学習を考える:次の配列を解くKMPアルゴリズム

1. アルゴリズム解析

これは、2022 年版 Wangdaoshu Data Structure の 110 ページにある KMP アルゴリズムによって解決される次の配列アルゴリズムです。原理は本書では詳しく説明されておらず、Xianyu 先輩も、これは、このアルゴリズムの中で最も曖昧なアルゴリズムの 1 つであると述べています。コース全体が、著者の思考を呼び起こしました。

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 であると判断できるため 、次は m+2です。      

2. だったら X!=Y の場合、文字列②に一致する文字列①を見つける必要があります。X の前に一致する文字列は最大 n 個あり、文字列②==文字列③、文字列①==文字列③なので  文字  ①②文字列に一致する文字列を見つけます。 、 この時点でξ==Yであれば、  next[Z]=n+1 of  Z 

上記のコードの 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],循环继续
    }

2、KMP テンプレート

 テンプレートの i=0 と j=-1は、プログラム内の文字列が添字 0 から始まるためであり、最初の文字の添字はデフォルトで 1 であると Wang Dao 氏は説明しています。

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 Wangdao の P111 の「4.2.3 KMP アルゴリズムのさらなる最適化」を参照してください。教科書

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