KMPアルゴリズムの詳細な説明(個人的な理解)

KMPアルゴリズムの詳細な説明

BFアルゴリズムは時間と労力を要する力ずくの方法であることがわかっているので、どうすればよいでしょうか。DEKnuth、J、H、Morris、VRPrattの3つの偉大な神々が、高速マッチングアルゴリズムであるKMPアルゴリズムを作成しました。このアルゴリズムの中核は、メインの文字列ポインターのバックトラックのプロセスを減らし、マッチングを大幅に改善することです。速度。
上記のメイン文字列ポインタのバックトラック、これは何ですか?KMPの実装手順について説明します。

1.手順

  • メイン文字列の次の値を取得するの
    は、KMPが照合前にメイン文字列の次の値を計算したため、BFのポインタバックトラックが減少するためです。あなたに例えを与えるために:
主串:ababbbab
子串:abb

第一轮匹配:匹配到了第一个字符
ababbbab
a
第二轮匹配:匹配到了第二个字符
ababbbab
ab
第三轮匹配:匹配失败
匹配失败之后BF算法是这样的,从主串第二个字符又开始匹配,这就较做主串指针回溯。
ababbbab
 abb

次のコードは、メイン文字列のnext []用です。

void getnext() {
    
    
    next[0] = -1;
    int i = 0, j = -1;
    int len = strlen(T);
    while(i < len) {
    
    
        if(j == -1 || T[i] == T[j])
            next[++i] = ++j;
         else
            j = next[j];
    }
}

次に取得する目的は、一致しない文字の前の部分文字列が同じプレフィックスとサフィックスを持っているかどうかを確認することです。同じプレフィックスとサフィックスがある場合は、直接スキップします。これは少し回避策です。すぐにスクリーンショット。したがって、KMPアルゴリズムは、ポインターのバックトラックの問題を回避します。
簡単にするために、バックトラッキングアルゴリズムは「ヒューリスティック」とも呼ばれます。問題を解決するとき、あなたがとるすべてのステップは試みる態度です。現在の選択が最善ではないとわかった場合、またはこのように続けた場合、あなたは間違いなくあなたの目標を達成しないでしょう、あなたはすぐに戻って選択するべきです再び。戻って失敗したときに戻るこの方法は、バックトラッキングアルゴリズムです。

マッチする

bool KMP() {
    
    
    getnext();
    int len1 = strlen(T);
    int len2 = strlen(S);
    int i = 0, j = 0;     //i指向模式串T,j指向主串S
    while(j < len2) {
    
    
        if(T[i] == S[j]) {
    
     
            i++;
            j++;
            if(i == len2) {
    
    
                return true;
            }
        } else {
    
    
            i = next[i];
            if(i == -1) {
    
    
                j++;i++;
            }
        }
    }
    return false;
}

ナンセンスな話をするのではなく、ただ写真に行ってください。上記のコードのプロセスを全員に示します
ここに画像の説明を挿入

特定のプロセス:
ここに画像の説明を挿入

ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
上の3つの写真を見ることができます。最初の5つは一致していますが、6つ目の写真が一致しない場合はどうすればよいですか?i = next[i]この構文、4番目の図の部分文字列がBを指すようにし、Bからペアリングを開始するために使用されます。

  • コード
#include <iostream>
#include<cstring>
#include <string>
typedef long long ll;
using namespace std;


bool KMP(char *T,char*S) {
    
    

    int next[100];
    next[0] = -1;
    int i = 0, j = -1;
    int len = strlen(T);
    while(i < len) {
    
    
        if(j == -1 || T[i] == T[j])
        {
    
    
          i++;
          j++;
          next[i] = j;
        }

         else
         {
    
    
             j = next[j];
         }

    }
    int len1 = strlen(T);
    int len2 = strlen(S);
    int i_ = 0, j_ = 0;     //i指向模式串T,j指向主串S

    while(j_ < len2) {
    
    
        if(T[i_] == S[j_]) {
    
    

            i_++;
            j_++;
            if(i_ == len2) {
    
    

                return true;
            }
        } else {
    
    

            i_ = next[i_];
            if(i_ == -1) {
    
    
                j_++;i_++;
            }
        }
    }
    return false;
}

int main()
{
    
    
	char a[] = "ABBABBABAB";
	char b[] = "ABBAB";
	bool m = KMP(a,b);
	printf("%d\n",m);
	return 0;
}

おすすめ

転載: blog.csdn.net/qq_45125250/article/details/109684508