KMPアルゴリズムの概要(南昌工科大学ACMトレーニング)
(最近の話題を考えると脳が痛い)
(他の誰かを引用します、それはとても良いです)
Knuth-Morris-Pratt文字列検索アルゴリズム(KMPアルゴリズム、0.0と呼ばれます)は、メインテキスト文字列S内の単語Wの出現位置を見つけることができます。
このアルゴリズムは、単語自体に、一致しない場合に次の一致が開始される場所を決定するのに十分な情報が含まれているという結果を使用して、以前に一致した文字を再チェックすることを回避します。
まず
、通常のマッチング文字列のアルゴリズムトピックを紹介します。
パターン文字列Sとテンプレート文字列Pが与えられた場合、すべての文字列には大文字と小文字の英字とアラビア数字のみが含まれます。
テンプレート文字列Pは、パターン文字列Sに部分文字列として複数回表示されます。
パターン文字列S内のテンプレート文字列Pのすべての位置の初期インデックスを計算します。
- 素朴なアルゴリズム(暴力)
(yのテンプレート質問を借りて使用します、ハハ)
#include<iostream>
using namespace std;
int main(){
string a,b;
cin>>a>>b;
for(int i=0;i<a.size()-b.size()+1;i++){
string c=a.substr(i,b.size());
if(c==b) cout<<i<<" ";
}
}
ただし、文字の長さが非常に長い場合は、タイムアウトになります。
それでKMPアルゴリズムが生まれました(ハハ、問題がアルゴリズムを作成します)
- -KMPアルゴリズムソリューション
ちょっと待って、KMPアルゴリズムの使い方を紹介しましょう
- 原理
マザー文字列abcdabc
文字列abc、
ナイーブアルゴリズムを使用すると、マザー文字列から1つずつ検索されます。
しかし、ストリングを何度も一致させたため、効率が無駄になり、時間が大幅に改善されました。
といった
マザー文字列abcdabc
文字列abc
マザー文字列abcdabc
文字列* abc
マザー文字列abcdabc
文字列** abc
マザー文字列abcdabc
文字列*** abc
マザー文字列abcdabc
文字列**** abc
この一致は非常に反復的であり、文字を複数回一致させる必要があります(悲しい)
-
kmpアルゴリズム
は、次の配列とkmpマッチングからなる2つのことによってkmpアルゴリズムを実装します。 -
次の配列は何ですか?次の配列は、主に
部分文字列の接頭辞と接尾辞の位置を格納します。p文字列では、
p [1- j] = p [i-j + 1、i]; -
kmpマッチング
これは部分文字列と親文字列のマッチングです。次の配列は、文字の繰り返しのマッチングを回避するために使用されます -
テンプレート
//next数组
for (int i = 2, j = 0; i <= m; i ++ )
{
while (j && p[i] != p[j + 1]) j = ne[j];
if (p[i] == p[j + 1]) j ++ ;
ne[i] = j;
}
// kmp匹配
for (int i = 1, j = 0; i <= n; i ++ )
{
while (j && s[i] != p[j + 1]) j = ne[j];
if (s[i] == p[j + 1]) j ++ ;
if (j == m)
{
// 匹配成功后的逻辑
j = ne[j];
}
}
簡単だと思いますか?理解できれば、この質問をすることができます
このように、あなたはすでに始め方について少し知識を持っています~~(KMPアルゴリズムはそれほど単純ではないので、ハハ)~~
ここで、KMPアルゴリズムを理解するための難易度を上げる必要があります
終了しました。現在、特定のフレームワークがあるようです。
CF KMPを試してみましょう。この
質問は、kmpの能力を完全に示しています。
この質問は、次の配列とkmpマッチングをより具体的に説明します
私のACコードを見てください( ACの喜び、ハハ)
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6+10;
int q[]={
1,2,3};
char p[4][N];
int ne[4][N];
int k[4][4];
int len[4];
int ans=0x7fffffff;
void getnext(int m,char p[],int k){
for(int i=2,j=0;i<=m;i++){
while(j&&p[i]!=p[j+1]) j=ne[k][j];
if(p[i]==p[j+1]) j++;
ne[k][i]=j;
}
}
int kmp(int n,int m,char s[],char p[],int k){
int j=0;
for(int i=1;i<=n;i++){
while(j&&s[i]!=p[j+1]) j=ne[k][j];
if(s[i]==p[j+1]) j++;
if(j==m) return -1;
}
return j;
}
void solve(int i,int j,int l){
if(k[i][j]>=0&&k[j][l]>=0) ans=min(ans,len[i]+len[j]+len[l]-k[i][j]-k[j][l]);
else{
if(k[i][j]<0&&k[j][l]<0) ans=min(ans,len[l]);
else if(k[i][j]<0) ans=min(ans,len[j]+len[l]-k[j][l]);
else if(k[j][l]<0) ans=min(ans,len[i]+len[l]-k[i][l]);
}
}
int main(){
scanf("%s%s%s",p[1]+1,p[2]+1,p[3]+1);
for(int i=1;i<=3;i++) len[i]=strlen(p[i]+1);
for(int i=1;i<=3;i++){
getnext(len[i],p[i],i);
for(int j=1;j<=3;j++){
if(i==j) continue;
k[i][j]=kmp(len[j],len[i],p[j],p[i],i);
}
}
do{
solve(q[0],q[1],q[2]);
}while(next_permutation(q,q+3));
cout<<ans;
return 0;
}
幸せな学習、アルゴリズムは長い道のりです、私はとても幸せです~~(Orz、来て私を救ってください)~~
Mengxinの小さな要約、0.0のいいねを指摘する大物を歓迎します
、私は子供たちを見るのが非常に難しいです/ (ㄒoㄒ)/ ~~