Vous êtes sur la page 1sur 5

El algoritmo de Boyer-Moore (Bob Boyer, Strother Moore 1977)

Busca todas las ocurrencias de un patrn o subcadena(P) en una cadena(T).


Recuerde que ello puede indicarse, ya sea donde se inician las ocurrencias, o en
las posiciones donde terminan.

Ejemplo:
Entrada: P=cc T=abcccbcc
Salida: 3, 4, 7
Pues P=cc ocurre en las posiciones 3, 4 y 7 de T=abcccbcc.
O bien,
Salida: 4, 5, 8
Pues P=cc ocurre en las posiciones finales 4, 5 y 8 de T.

A diferencia del algoritmo de fuerza bruta que compara P con un primer pedazo de
T -de izquierda a derecha-, luego avanza P (shift P) una posicin, vuelve a
comparar, etc.:
abcccbcc abcccbcc
ccc ccc

comparamos 'c' con 'a' comparamos 'c' con 'b' etc.


como falla, shift P una posicin --> como falla, shift P una posicin -->

[note que la comparacin se hace [note que la comparacin se hace


de izquierda a derecha] de izquierda a derecha]

Boyer-Moore es un algoritmo que pretende que el shift (desplazamiento) de P sea


-a veces- ms largo que una sola posicin -deseablemente un shift mucho ms
largo-. Eso hara que el algoritmo sea ms veloz que el de fuerza bruta -en
promedio-.
Asumiremos que |P| = n y |T| = m (las posiciones de P y T empiezan en 1).

Se basa en dos nuevas ideas:


i) Que la comparacin (de P con cada pedazo de T) se haga de derecha a
izquierda.
ii) Que la forma de avanzar P (shift P) se haga de manera ms inteligente
utilizando la regla que mejor resulte (la que de un shift ms largo) de entre
las siguientes:
la BCR (regla del mal carcter) y la GSR (regla del buen sufijo).

El algoritmo Boyer-Moore simplificado


Se conoce como Boyer-Moore simplificado al algoritmo resultante de utilizar slo
la regla BCR.
Regla del mal carcter (Bad Character Rule, BCR)

Cuando comparamos P con un pedazo de T y las comparaciones son exitosas


hasta un carcter que no coincide, por ejemplo con

T a b c e r d g d r e f r e
P e g t d h d r

la 'r' coincide (recuerde que la comparacin es de derecha a izquierda)


la 'd' coincide
la 'g' no coincide con la 'h'. Esta 'g' es el "mal" carcter de T.
Debemos desplazar P (shift P).

Ntese que si avanzamos P una posicin, la 'g' tampoco coincidir con 'd'.
Si avanzamos dos posiciones, la 'g' tampoco coincidir con 't':
Si hay una 'g' en P, es mejor desplazar P hasta que coincida con la 'g' de T.

En el ejemplo T[1]=a, T[2]=b,, T[k]=g para k=7.


En el ejemplo P[1]=e, P[2]=g,, P[i]=h para i=5.

Note que si no hay g en P, por ejemplo P=eotdhdr, el desplazamiento sera an


mayor: el primer smbolo e de P debiera colocarse luego de la g de T.

Est claro que la 'g' que buscamos en P debe estar a la izquierda de la posicin
donde est el "mal" carcter g de T.

Por ejemplo con


T a b c e r d g d g e f r e
P e g t d h d g
Coinciden - de derecha a izquierda- las 'g', las 'd'.
Pero 'g' y 'h' no coinciden.
Deberamos avanzar P -dado que hay una 'g' en P a la izquierda del "mal"
carcter-, hasta que coincida con la 'g' de T en T[7].

Lamentablemente hacer esto requiere demasiados clculos.


Pero, la regla BCR imaginada por Boyer-Moore, busca -en P- el "mal" carcter de
T ( en el ejemplo T[k] = T[7] = g ), pero lo busca lo ms a la derecha posible de de P y
desplaza P hasta que dicho caracter est a la altura de T[k].
Ntese que en el ejemplo, ello derivara en retroceder P! en vez de avanzarlo. Por
ello esta regla dice que si tal es el caso se avance slo una posicin.
Esta decisin de buscar el "mal" carcter T[k] no a la izquierda de la posicin en
que est dicho "mal" carcter, sino lo ms a la derecha de P, no es la mejor de las
decisiones desde el punto de vista lgico, pero es una buena decisin cuando nos
enteramos que dicha bsqueda puede hacerse con muy poco espacio adicional y
en un tiempo sumamente rpido con un pre-procesamiento previo en P as:

Para cada carcter aj en el alfabeto (de T (y P)), sea R[aj] la posicin ms a la


derecha de P en la que ocurre aj (cero si no ocurre aj en P).

Es muy fcil construir los valores R[aj] para cualquier P.

Ejemplo:
Reduciremos el alfabeto a {a,b,c,d,e,f,g,h,r,t}

P = egtdhdg

R[a] R[b] R[c] R[d] R[e] R[f] R[g] R[h] R[r] R[t]
0 0 0 6 1 0 7 5 0 3

Ntese que un algoritmo que construya estos valores lo puede hacer recorriendo P
una sola vez en O(n):
Para i=1 hasta n
R[P[i]] = i;
FinPara

La regla BCR es como sigue:


Sea que P est alineada con una parte de T y los n-i caracteres de ms a la
derecha coinciden pero el siguiente carcter a la izquierda, llammoslo P[i] no
coincide con -el "mal" carcter-T[k]:
Desplace P un nmero de posiciones igual a max{ 1, i-R[T[k]] }

Por ejemplo con


T a b c e r d g d g e f r E
P e g t d h d g

R[a] R[b] R[c] R[d] R[e] R[f] R[g] R[h] R[r] R[t]
0 0 0 6 1 0 7 5 0 3

|P|=n=7 |T|=m=13 T[k]=g para k=7 P[i]=h para i=5.

En P y T: coinciden -de derecha a izquierda-: los n-i=2 caracteres de ms a la derecha


Pero 'g' y 'h' no coinciden. T[k] no coincide con P[i].
Debemos desplazar P: max{ 1, 5-R[g] } = max{ 1, 5-7 } = 1 (una posicin)

Ya dijimos que si el "mal" carcter no est en P esta regla desplaza P:


i - R[T[k]] = i - 0 = i posiciones. Lo cual es completamente lgico.
El algoritmo Boyer-Moore-Horspool (BMH)

Nigel Horspool se dio cuenta que en vez de utilizar como el mal carcter, el
carcter de T que hace que las comparaciones fallen:
T = pastbdtubaevqxrshhhhhhxzzzzzhhh
P = actbdrxdae
En este caso el smbolo b es el "mal carcter".

Es posible trabajar con cualquier otro a la derecha. En particular con el carcter de


T que est junto al ltimo carcter de P (a la derecha).
T = pastbdtubaevqxrs
P = actbdrxdae
En este caso el smbolo e es el (nuevo) "mal carcter".

Pero como el carcter de T que est junto al ltimo carcter de P (a la derecha)


puede ser parte de las coincidencias, entonces debemos modificar un poco el pre-
procesamiento de P: Su ltimo smbolo no debe considerarse al calcular la tabla
R.
Recordemos que: para cada carcter aj en el alfabeto, sea R[aj] la posicin ms a
la derecha de P en la que ocurre aj (cero si no ocurre aj en P).

As entonces, la tabla R para, por ejemplo, P = egtdhdg


ya no es
R[a] R[b] R[c] R[d] R[e] R[f] R[g] R[h] R[r] R[t]
0 0 0 6 1 0 7 5 0 3

Sino que obviamos su ltimo smbolo: P = egtdhdg


quedando R as:

R[a] R[b] R[c] R[d] R[e] R[f] R[g] R[h] R[r] R[t]
0 0 0 6 1 0 2 5 0 3
El algoritmo Boyer-Moore-Sunday (BMHS o BMS)

D. M. Sunday tiene una idea semejante, pero en vez de usar el carcter (de T) que
est junto al ltimo carcter de P (a la derecha), sugiere utilizar el carcter (de T)
que est inmediatamente despus.

En este caso R se calcula como en el algoritmo original sin obviar ningn smbolo.

Por ejemplo:
T= pastbdtubaevqxrsxxxxxxxhhhhh
P= actbdrxdae
En este caso el smbolo "v" es el "mal carcter".

Ntese que en BMH y BMS el clculo i-R(T[k]), ahora es algo semejante a


n-R(T[k]), que puede pre-procesarse para todo el alfabeto y guardarse en una
tabla de desplazamientos (llamada skip a veces).

Las ideas de Sunday y Horspool no son una inspiracin arbitraria sino que
fundamentan y acompaan sus ideas con datos empricos que muestran su vala,
como puede leerse en sus artculos originales.

Ejemplo muy popular (pero sesgado) donde se ve en la ltima lnea los saltos que
haran estos tres algoritmos:

1 2 3 4 5 6 7 8 9 10 ... 1 2 3 4 5 6 7 8 9 10 ... 1 2 3 4 5 6 7 8 9 10 ...


a b c a b d a a c b a a b c a b d a a c b a a b c a b d a a c b a
b c a a b b c a a b b c a a b
b c a a b b c a a b b c a a b

(a) Boyer-Moore (b) Horspool (c) Sunday

Vous aimerez peut-être aussi