C++BMアルゴリズム

2739 ワード

BMアルゴリズムは非常に有名な文字列検索アルゴリズムです.
文字列検索アルゴリズムの中で最も有名な2つはKMPアルゴリズム(Knuth−Morris−Pratt)とBMアルゴリズム(Boyer−Moore)である.両方のアルゴリズムは、最悪の場合、線形の検索時間を有する.しかし、実用的には、KMPアルゴリズムは最も簡単なcライブラリ関数strstr()よりもそれほど速くないが、BMアルゴリズムはKMPアルゴリズムより3〜5倍速いことが多い.
BMアルゴリズムについて説明します.
1,BMアルゴリズムはBoyer-Mooreアルゴリズムの略称であり、BoyerとMooreによって提出された. 
2,BMアルゴリズムも高速シリアルマッチングアルゴリズムであり,BMアルゴリズムとKMPアルゴリズムの主な違いはマッチング動作の方向が異なることである.BMアルゴリズムはマッチング操作の文字比較順序のみを右から左に変更するが、マッチングに失敗した場合、モードTの右シフトの算出方法は大きく変化する. 
3、スライド距離関数:
議論を容易にするために、BMアルゴリズムの鍵は、所与のモードT="t 0 t 1...tm"に対して文字から正の整数へのマッピングを定義することである.
dist :c->{1,2,…,m+1} 
関数distはスライド距離関数と呼ばれ、本文に現れる可能性のある任意の文字のモードにおける位置を与える.関数distは次のように定義されます.
dist(c)=m-j jは、モードにおけるcの下付き記号であり、後のものを基準とする
dist(c)=m+1 cがモードにない場合またはc=tm
例えば、T="pattern"であれば、dist(p)=6−0=6、dist(a)=6−1=5、
dist(t)= 6 – 3 =3
,dist(e)= 2, dist(r)= 1, dist(n)= 6 + 1 = 7. 
4,BMアルゴリズムの基本思想は,主列中の位置iから左へのサブ列とパターンを右から左へマッチングする過程で,不整合が発見された場合,次は主列のi+dist(si)位置から新たなマッチングを再開すべきであると仮定し,その効果は、モードと主列を右にスライドさせる距離dist(si)に相当し、比較を必要とせずにdist(si)文字をスキップすることに相当する.
次のような例があります.
FINDINAHAYSTACKNEEDLEINAからNEEDLEを検索するプロセス:
i    j    00    01    02    03    04    05    06    07    08    09    10    11    12     13    14    15    16    17    18    19    20    21    22    23
          F      I       N      D     I      N     A      H     A      Y    S      T      A       C     K      N    E      E     D      L     E      I       N      A
0   5   N     E      E      D     L       E
5   5                                           N     E      E      D     L      E
11 4                                                                                           N       E       E     D    L     E
15 0                                                                                                                             N     E      E     D     L     E
レイアウトがうまくいかないので、ご了承ください
ステップ1:i=5,j=5失敗dist(N)=5なので5+5=10に右に移動
ステップ2:i=10,j=5失敗dist(S)なしで右に10+6=16に移動
ステップ3:i=15、j=4はdist(N)=5に失敗したので、15+5=20に右に移動してマッチングに成功しました
インスタンスコード:
#include 
#include 
using namespace std;

int Dist(char *t,char ch)
{
    int len = strlen(t);
    int i = len - 1;
    if(ch == t[i])
      return len;
    i--;
    while(i >= 0)
    {
      if(ch == t[i])
         return len - 1 - i;
      else
         i--;
    }
    return len;
}

int BM(char *s,char *t)
{
    int n = strlen(s);
    int m = strlen(t);
    int i = m-1;
    int j = m-1;
    while(j>=0 && i