MODULE ADruS193_БМ; (* Поиск в тексте. Алгоритм Бойера и Мура, раздел *) IMPORT Log := StdLog, In := i21sysIn, КМП := ADruS192_KMP; CONST Mmax = 10; Nmax = 1000; VAR s: ARRAY Nmax OF CHAR; N: INTEGER; p: ARRAY Mmax OF CHAR; M: INTEGER; (* реализация предикатов, определенных в тексте *) PROCEDURE P ( i, j: INTEGER ): BOOLEAN; VAR k: INTEGER; BEGIN k := j; WHILE ( k < M ) & ( s[ i-M+k ] = p[ k ] ) DO INC( k ) END; RETURN k = M END P; PROCEDURE R ( i: INTEGER ): BOOLEAN; VAR j: INTEGER; BEGIN RETURN P( i, 0 ) END R; PROCEDURE Q ( i: INTEGER ): BOOLEAN; VAR k: INTEGER; BEGIN k := M; WHILE ( k < i ) & ~R( k ) DO INC( k ) END; RETURN ~( k < i ) END Q; (**********************************************************************) PROCEDURE Search ( IN p, s: ARRAY OF CHAR; M, N: INTEGER; OUT r: INTEGER ); (* поиск образца p длины M в тексте s длины N; M <= Mmax *) (* если p найден, то r указывает его позицию в s, иначе r = -1 *) VAR i, j, k: INTEGER; d: ARRAY 128 OF INTEGER; BEGIN FOR i := 0 TO 127 DO d[i] := M END; FOR j := 0 TO M-2 DO d[ ORD( p[j] ) ] := M-j-1 END; (* инвариант цикла Q(i) & P(i-j,j); проверки (показаны красным) вставлены, для ясности с избытком, всюду, где инвариант должен выполняться *) i := M; j := M; k := i; ASSERT( Q(i) & P(i, j) & (k = i-M+j) ); LOOP IF (j > 0) & (i <= N) & (s[k-1] = p[j-1]) THEN ASSERT( Q(i) & P(i, j) & (k = i-M+j) ); DEC(k); DEC(j); ASSERT( Q(i) & P(i, j) & (k = i-M+j) ); ELSIF (j > 0) & (i <= N) THEN ASSERT( Q(i) & P(i, j) & (k = i-M+j) ); i := i + d[ ORD( s[i-1] ) ]; j := M; k := i; ASSERT( Q(i) & P(i, j) & (k = i-M+j) ); ELSE EXIT END END; ASSERT( Q(i) & P(i, j) & (k = i-M+j) ); IF j = 0 THEN r := k ELSE r := -1 END; END Search; (*****************************************************************************) PROCEDURE Проверить*; VAR r: INTEGER; BEGIN Log.Ln; Log.String('Проверяем Бойера-Мура:'); Log.Ln; In.Open; ASSERT( In.done ); In.String( s ); ASSERT( In.done ); N := LEN( s$ ); In.String( p ); ASSERT( In.done ); M := LEN( p$ ); Search( p, s, M, N, r ); Log.Int( r ); Log.Ln; END Проверить; END ADruS193_БМ.