Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Точный поиск подстроки в строке - Алгоритм Боуера-Мура

Автор: Thierry Lecroq
Перевод: Кантор И.

Ну вот мы и пришли к этому, одному из наиболее известных и, эффективных ( Это особенно касается его дальнейших улучшений ) для ОБЫЧНЫХ ПРИЛОЖЕНИЙ ( то есть редакторов текста, например ) алгоритму.

Он совершает 3n сравнений в худшем случае при поиске первого совпадения с непериодничным образцом и O( n*m ) при поиске всех вхождений.

Он производит сравнения справа налево, начиная с самого правого символа. В случае несовпадения ( или, наоборот, полного попадания ) используются две заранее вычисляемые функции: функция плохого символа и функция хорошего суффикса.

Предположим, что несовпадение произошло между символом образца x[j] = b и символом текста y[ i+j ] = a на позиции i.

Тогда y[ i+j+1, i+m-1 ] = x[ j+1, m-1 ] = u и y[ i+j ] =/= x[j]. Функция хорошего суффикса состоит в 'выравнивании' сегмента y[ i+j+1, i+m-1 ] = x[ j+1, m-1 ] = u по его самому правому появлению в x, так чтобы ему предшествовал символ, несовпадающий с x[ j ] ( см Рис.1 ).

Если такого сегмента нет, то сдвиг выравнивает наибольший суффикс v отрезка y[i+j+1,i+m-1] по совпадающему префиксу x ( см Рис.2 ).

Функция плохого символа выравнивает символ текста y[ i + j ] по его самому правому появлению в x[ 0 ... m - 2] ( см Рис.3 ). Если его там нет - сдвигаем на всю длину образца: левый конец теперь - y[ i + j + 1 ] ( см Рис.4 ).

Для сдвига образца мы берем минимум этих двух функций.

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

сдвиг функции плохого символа хранится в таблице bc размера s, а сдвиг функции хорошего суффикса - в таблице gs размера m + 1.

Для a из S:

bm_bc[ a ] = min{ j | 1 <= j < m и x[ m - 1 - j ] = a }, если a появляется в x и
bm_bc[ a ] = m в противоположном случае.

Определим два условия:

cond 1 ( j, s ) : для каждого k, такого что j < k < m, s >= k или x[ k-s ] = x[k]
cond 2 ( j, s ) : если s < j то x[ j-s ] =/= x[ j ].

Тогда для 0 <= i < m имеем:

bm_gs[ i+1 ] = min{ s > 0 | cond 1 ( i, s ) AND cond 2 ( i, s ) hold}

А bm_gs[0] - длина наименьшего периода x.

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

/* 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[ (unsigned char)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 - i;
       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 BM( char *x, char *y, int n, int m ) {
  int i, j, bm_gs[XSIZE], bm_bc[ASIZE];
  
  /* Preprocessing */
  PRE_GS( x, m, bm_gs ); 
  PRE_BC( x, m, bm_bc );
  i=0; 
  while ( i <= n-m ) {
     for ( j=m-1; j >= 0 && x[j] == y[ i+j ];  --j ); 
    if ( j < 0 ) {
       OUTPUT(i); 
      i += bm_gs[ j+1 ]; 
    }
    else i += MAX(( bm_gs[ j+1 ]), ( bm_bc[ (unsigned char)y[ i+j ] ] - m + j + 1 ) ); 
   }    
} 
Проект Delphi World © Выпуск 2002 - 2024
Автор проекта: USU Software
Вы можете выкупить этот проект.