Tурбо-БМ

     Турбо - БМ является улучшением алгоритма Боуера - Мура. Мы будем запоминать сегмент текста, который сошелся с суффиксом образца во время прошлой попытки ( и только, если произошел сдвиг хорошего суффикса ).

     Это даст нам два преимущества:

     1. Возможность перескочить через этот сегмент

     2. Возможность применения 'турбо - сдвига'

     Турбо - сдвиг может произойти, если мы обнаружим, что суффикс образца, который сходится с текстом, короче, чем тот, который был запомнен ранее.

     Пусть u - запомненный сегмент, а v - cуффикс, совпавший во время текущей попытки, такой что uzv - суффикс x. Тогда av - суффикс x, два символа а и b встречаются на расстоянии p в тексте, и суффикс x длины |uzv| имеет период длины p, а значит не может перекрыть оба появления символов а и b в тексте. Наименьший возможный сдвиг имеет длину |u| - |v| ( его мы и называем турбо - сдвигом ).



Применение турбо-сдвига в случае |v| < |u|.

     При |v| < |u|, если сдвиг плохого символа больше, то совершаемый сдвиг будет больше либо равен |u| | 1. В этом случае символы c и d различны, так как мы предположили, что предыдущий сдвиг был сдвигом хорошего суффикса. Тогда сдвиг больший, чем турбо-сдвиг, но меньший |u| + 1 совместит c и d с одним и тем же символом v. Значит, если сдвиг плохого символа больше, то мы можем применить сдвиг больший, либо равный |u| + 1.



Нельзя совместить символы c =/= d с одним и тем же символом v.


Реализация на Си


/* 

In TBM function variable u memorizes the length

 of the suffix matched during  the previous attempt

  and the variable v memorizes the length of the suffix

 during the current attempt.

*/



/* Preprocessing of the Bad Character function shift */

PRE_BC( char *x, int m, int bm_bc[] ) {

   int a, j; 

   

   for ( a=0; a < ASIZE; a++ ) bm_bc[ a ] = m; 

   for ( j=0; j < m-1;  j++ ) bm_bc[ x[ j ] ] = m - j - 1; 

  }

 

 /* Preprocessing of the Good Suffix function shift  */

 PRE_GS( char *x, int m,  int bm_gs[] ) {

   int i, j, p, f[XSIZE];

   

   memset( bm_gs, 0, ( m + 1 ) * sizeof( int ) );

   f[ m ] = j = m + 1; 

   for (i=m; i > 0; i-- ) {

      while ( j <= m && x[ i - 1 ] != x[ j - 1 ] ) {

        if ( bm_gs[ j ] == 0 ) bm_gs[ j ] = j - 1;

       j = f[ j ];

     }

     f[ i - 1 ] = --j; 

   }

   p=f[ 0 ]; 

   for ( j=0; j <= m; ++j ) {

      if ( bm_gs[ j ] == 0 ) bm_gs[ j ] = p; 

     if ( j == p ) p = f[ p ]; 

   }

}



/* Boyer-Moore string matching algorithm */

void TBM( char *x, char *y, int n, int m ) {

  int i, j, u, shift, v, turbo_shift, bm_gs[XSIZE], bm_bc[ASIZE];

  

  /* Preprocessing */

  PRE_GS( x, m, bm_gs ); 

  PRE_BC( x, m, bm_bc );

  

  i = u = 0;

  shift = m;

  while ( i <= n-m ) {

     j = m - 1;

    while ( j >= 0 && x[ j ] == y[ i + j ] ) {

       --j;

      if ( u != 0 && j == m - 1 - shift ) j -= u;

   }

   if ( j < 0 ) {

      OUTPUT( i );

      shift = bm_gs[ 0 ];

      u = m - shift;

   }

   else {

      v = m - 1 - j;

      turbo_shift = u - v;

      bc_shift = bm_bc[ y[ i+j ] ] - m + j + 1;

      shift = MAX ( turbo_shift, bc_shift );

      shift = MAX ( shift, bm_gs[ j+1 ] );

      if ( shift == bm_gs[ j+1 ]) u = MIN( (m - shift), v );

      else {

         if ( turbo_shift < bc_shift ) shift = MAX (shift, (u+1) );

         u = 0;

      }

   }

   i += shift;

 }

}

   


Назад К началу странички

Вверх по каталогу
Вперед



Построение автомата Алгоритм грубой силы
Алгоритм Боуера-Мура Алгоритм Хорспула
Алгоритм Карпа-Рабина Алгоритм Кнута-Морриса-Пратта
Алгоритм Морриса-Пратта Не такой уж наивный алгоритм
Алгоритм Сдвига-Или