I.はじめに
コンピュータサイエンス、クヌース - モリス - プラット列検索アルゴリズム(単にKMPアルゴリズムとも呼ばれる)でメインテキストストリングSに単語出現位置Wを見つけるために このアルゴリズムは、それ自体が再検討する以前にマッチした文字を避けるために場所を見つけることが開始されます一致を使用して、次を決定するのに十分な情報が含まれている単語と一致していません。このアルゴリズムは、ガートナーとヴォーン・プラット、ジェームズは・H・モリスはまた、独立して共同で1977年に最後の3つによって公開されたアルゴリズムを、考案した同じ年によって1974年に考案されました。(投稿者:ウィキペディア)
検索KMP(クヌース-モリス-プラットのstring-検索は) マッチングが短く、文字列照合ステップで不要なバックを回避することにより、暴力マッチングアルゴリズムの欠点のいくつかを構成する文字列照合アルゴリズムより効率的なアルゴリズムであり、時間は、それだけではO(n-M +)の時間複雑で非常に便利なタイムクリティカルな状況での使用に適した、だけでなく、いくつかのテストサイトのゲーム、。しかし、この方法は、基本的にACオートマトンの特殊なケースで、理解するいくつかの困難があります。この記事では、関連する数学上の命令は関連するセクションに一致する「はじめのアルゴリズムに」という文字列を参照することができ、KMPアルゴリズムを理解し、実装する方法を説明します。
第二に、コード
以下は、あなたが確認してから分析を行うことができ、実装コードです。
#include <stdio.h>
#include <string.h>
void getnext(char *t); //计算子串的状态转移数组的函数
int kmp(char *s,char *t); //kmp算法的主要匹配搜索函数
int next[255]; //全局next数组更方便调用,大小根据实际情况更改
int main(void)
{
int n;
char s[255],t[255];
printf("母串:");
scanf("%s",s);
printf("子串:");
scanf("%s",t);
n=kmp(s,t);
if(n==0)
printf("匹配失败\n");
else
printf("在第%d位匹配成功",n);
return 0;
}
void getnext(char *t)
{
int i=0,j=-1,l=strlen(t); //j初始化为-1只是方便计算,更易于理解,无特殊含义。
next[0]=-1; //这里如果用next[i]=j后续有可能出现死循环,故单独赋值。
while(i<l)
{
if(j==-1||t[i]==t[j]) //t[i],t[j]分别表示前缀子串单个字符和后缀子串单个字符,若匹配成功则以一种累加
{ //的方式继续向后匹配,所以每次比较一个字符,可以动手尝试分步理解
++i,++j;
if(t[i]!=t[j]) //这里是针对原先方法的一些优化,后续会将
next[i]=j;
else
next[i]=next[j];
}
else
j=next[j]; //字符不相同时进行回溯
}
}
int kmp(char *s,char *t)
{
int i=0,j=0;
int sl=strlen(s),tl=strlen(t);
getnext(t);
while(i<sl&&j<tl)
{
if(j==-1||s[i]==t[j])
++i,++j;
else
j=next[j]; //字符串失配时回溯到正确位置再次匹配
}
if(j==tl)
return i-tl+1;
else
return 0;
}
三、具体分析
1次転写配列と分析を求める方法
部分文字列の文字列sとtがあります。
S = "abcdefgab"
T = "abcdex"。
我々は唯一の第六のミスマッチで、二つの文字列の最初の5つの文字がそれぞれ等しく、それを見ることができます。試合は再びそれを一致させるために暴力に合わせて必要な場合。しかし、我々は、イニシャルの異なる、sの文字列であり、頭字語トンの文字列が同じで、それはサブストリングトンの最初の文字は2-5の親列では不可能であることを意味し6文字のサブストリング、観察して見ることができます試合の間の文字は、この時間は、いくつかの暴力的なマッチングステップが完全に省略されているがあり、その後の文字は同じようにスキップ見ることができます。私たちは、S [5]を知っていても、そのため!= T [5]、T [0]!= T [5]、我々は、彼らが2試合を維持する必要があるので、T [0]は、確かに、[5]は秒を意味するものではありません確認することはできませんその時の。
T [I] == S [I](Iは0,1,2,3,4 =)を
T [0] = T [J](J = 1,2,3,4)は!
導入することができる:T [0 ]!= S [J]( J = 1,2,3,4)
上記の例を通して、私たちはKMPアルゴリズムを見ることができますどのような具体的なバックトラックに基づいており、我々は暴力の試合は良いニュースよりも、このような遡及的な方法を見ることができます。私たちは、親の文字列にマッチする部分文字列を取るしようとしているので、それは次の文字列値に対応するそれぞれの親の文字列とは何の関係もない、と言うことですデジタルバックトラックのサブストリングに確実にポイントです。私たちは、今、私たちが今トンをサブストリングいる状況の文字の繰り返しを確認するために続けることができます
トン= "abcabx"
私たちは、最初の2つの概念を理解する必要があります「接尾辞」「接頭語」とを 「プレフィックス」組立文字列の最後の文字を除いて、全頭を指します。すべての尾の組み合わせの文字列の最初の文字を除いて、「サフィックス」を意味します。公共の値は、最大長「接頭辞」と「接尾辞」最長の全元素です。次に、算出された値がn-1の前の文字から成る最大共通の文字列であるnビットのアレイへJ次のインデックスポイントは、次のように文字列配列を記載されているときに不一致ビットn転移は、それはビットnを考慮していません。我々は、SO 2の対応するxの値に、「AB」が繰り返されている見つけることができることは公共の次の配列、の最大値であり、次に配置される[0] = - 1つの利点は、簡単より鮮やか、理解します。xにおけるミスマッチした後ならば、我々は一体的に第二ABがマッチングcから以降継続する前に、最初の位置に移動後、AB移動に対応するように後方に移動することができます。
同じ文字の次以降の値を交換するのは初めての値は、次のアレイ法の前にいくつかのケースを避けるために求めることができれば、私達はちょうどtは実際には、2つのA、B 2が含まれている文字列を検索し、考えることを続行欠陥の試合を繰り返し、この欠陥は、同じ文字のいくつかの連続した文字列に発生します。理由は話して起動しない、あなたは結果を得るために、文字列「aaaabcde」と「aaaaax」を分析するために、以前のメソッドを使用することができます。最後に、配列を以下の横図の文字列をtは、自分自身を追求しようとすることができます。
この時点で、我々は次のシフトのサブ文字列の配列を取得します。
分析2.kmpマッチング機能
KMP検索機能は、次の機能を理解する上で主な困難、結合文字列と行と一致するように、次のハンドルの文字列の配列は比較的簡単です。戻り値0マッチが失敗した場合、試合がうまくマッチした位置復帰成功しています。また、必要に応じて、これはちょうどKMPもっともシンプルな使用法である、あなたは、例えば、ほとんどの子供の列、マスター文字列が表示され、その上した文字列を祈る区域のために、彼の機能を向上させることができます。
第四に、の終わり
実際には、そこにこのようなアルゴリズム日曜日マッチングアルゴリズムを、より優れた文字列のパターン、およびKMPよりも若干高い効率のような他の多くの文字列照合アルゴリズムは、ですが、KMPアルゴリズムを理解しても、私たちはより良い他のアルゴリズムを理解するのに役立ちます。