Auxs: Bárbara Poblete, Rhodrigo Meza, Rodrigo Paredes
Búsqueda en texto: algoritmo Knuth-Morris-Pratt (KMP)
Suponga que se está comparando el patrón y el texto en una posición dada, cuando se encuentra una discrepancia.

La ventaja de KMP, es que permite avanzar varias posiciones a la vez, gracias a la función de fracaso:

Intuitivamente, f(j) es el largo del mayor prefijo de X que además es sufijo de X. Note que j = 0 es un caso especial, puesto que si hay una discrepancia en b0 el patrón se desliza en una posición.
Si se detecta una discrepancia entre el patrón y el texto cuando se trata de calzar bj+1, se desliza el patrón de manera que bf(j) se encuentre donde bj se encontraba, y se intenta calzar nuevamente.

El algoritmo para generar la función de fracaso es el siguiente (es similar al algoritmo KMP):
// m es largo del patron
// los indices comienzan desde 1
int[] f=new int[m];
f[1]=0;
int j=1;
int i;
while (j<m)
{
i=f[j];
while (i>0 && patron[i+1]!=patron[j+1])
{
i=f[i];
}
if (patron[i+1]==patron[j+1])
{
f[j+1]=i+1;
}
else
{
f[j+1]=0;
}
j++;
}
Ejemplo 1. analicemos el patrón aabaaa
| Comentarios | |||||||
| patrón (p[]) | a | a | b | a | a | a | |
| fn. fracaso (f[]) | 0 | inicializaciones: f[1] = 0, j = 1, Intuitivamente: 0, 1, 0, 1, 2, 2 | |||||
| fn. fracaso (f[]) | 0 | 1 | i = f[j=1]= 0
i = 0 => no entra al while p[i+1=1] == p[j+1=2] => f[j+1=2] = i+1 = 1 j = 2 |
||||
| fn. fracaso (f[]) | 0 | 1 | 0 | i = f[j=2]= 1
i = 1 => entra al while, p[i+1=2] != p[j+1=3] => i = f[i=1] = 0, sale del while p[i+1=1] != p[j+1=3] => f[j+1=3] = 0 j = 3 |
|||
| fn. fracaso (f[]) | 0 | 1 | 0 | 1 | i = f[j=3]= 0
i = 0 => no entra al while p[i+1=1] == p[j+1=4] => f[j+1=4] = i + 1 = 1 j = 4 |
||
| fn. fracaso (f[]) | 0 | 1 | 0 | 1 | 2 | i = f[j=4]= 1
(i = 1) && (p[i+1=2] == p[j+1=5] ) => no entra al while p[i+1=2] == p[j+1=5] => f[j+1=5] = i + 1 = 2 j = 5 |
|
| fn. fracaso (f[]) | 0 | 1 | 0 | 1 | 2 | 2 | i = f[j=5]= 2
i = 2 => entra al while, p[i+1=3] != p[j+1=6] => i = f[i=2] = 1, p[i+1=2] == p[j+1=6], sale del while p[i+1=2] == p[j+1=6] => f[j+1=6] = i + 1 = 2 j = 6, sale while principal |
Ejemplo 2. analicemos el patrón ababac
| Comentarios | |||||||
| patrón (p[]) | a | b | a | b | a | c | |
| fn. fracaso (f[]) | 0 | inicializaciones: f[1] = 0, j = 1, Intuitivamente: 0, 0, 1, 2, 3, 0 | |||||
| fn. fracaso (f[]) | 0 | 0 | i = f[j=1]= 0
i = 0 => no entra al while p[i+1=1] != p[j+1=2] => f[j+1=2] = 0 j = 2 |
||||
| fn. fracaso (f[]) | 0 | 0 | 1 | i = f[j=2]= 0
i = 0 => no entra al while p[i+1=1] == p[j+1=3] => f[j+1=3] = i+1= 1 j = 3 |
|||
| fn. fracaso (f[]) | 0 | 0 | 1 | 2 | i = f[j=3]= 1
(i = 1) && (p[i+1=2] == p[j+1=4] ) => no entra al while p[i+1=2] == p[j+1=4] => f[j+1=4] = i + 1 = 2 j = 4 |
||
| fn. fracaso (f[]) | 0 | 0 | 1 | 2 | 3 | i = f[j=4]= 2
(i = 1) && (p[i+1=3] == p[j+1=5] ) => no entra al while p[i+1=3] == p[j+1=5] => f[j+1=5] = i + 1 = 3 j = 5 |
|
| fn. fracaso (f[]) | 0 | 0 | 1 | 2 | 3 | 0 | i = f[j=5]= 3
i = 3 => entra al while, p[i+1=4] != p[j+1=6] => i = f[i=3] = 1, p[i+1=2] != p[j+1=6] => i = f[i=1] = 0, sale del while p[i+1=1] != p[j+1=6] => f[j+1=6] = 0 j = 6, sale while principal |
Búscando casos malos:
Supongamos que el texto esta compuesto por 10 letras a:
aaaaaaaaaa
Y que nuestro patrón es aaaab. Claramente este es un peor caso para fuerza bruta, gasta O(n*m) para decir que falló
la función de fracaso KMP es:
| patrón (p[]) | a | a | a | a | b |
| función de fracaso (f[]) | 0 | 1 | 2 | 3 | 0 |
KMP realiza la siguiente ejecución:
aaaab
12345
aaaaaaaaaa
1234
34
34
34
34
34
34
KMP gasta O(n+m) para decir que falló!!
Búsqueda en texto: algoritmo Boyer-Moore-Horspool (BMH)
Los algoritmos Fuerza Bruta y Knuth-Morris-Pratt (KMP) tratan de calzar el patrón buscado en el texto de izquierda a derecha, como se muestra en la siguiente figura:

Boyer y Moore sugirieron un método alternativo: buscar dentro del patrón de derecha a izquierda, mientras el patrón completo se mueve en el texto de izquierda a derecha, tal como se muestra en la siguiente figura:

Horspool realizó algunas simplificaciones al algoritmo original, resultando el algoritmo conocido como BMH. La idea de BMH es:
siguiente(s):
Texto: analisis de algoritmos Patrón: algo Tabla siguiente: g->3 l->2 a->1 analisis de algoritmos algo algo algo algo algoEficiencia del algoritmo: En promedio, si m es el largo del patrón, n el largo del texto y c el tamaño del alfabeto, el número esperado de comparaciones es n(1/m+1/2c).
Ejemplo 3. Calculemos la tabla siguiente del patrón abracadabra
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ejemplo 4. Calculemos la tabla siguiente del patrón australopitecus
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Otro ejemplo de BMH:
Texto: se hacen armarios a pedido
Patrón: armar
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
se hacen armarios a pedido
armar
, en el texto hay una a, luego la alineamos con la
última a del patrón
armar
, en el texto hay una c, saltamos el patrón
completo
armar
, en el texto hay una r, luego la alineamos con la
última r del patrón, sin contar la última
letra
armar
, patrón encontrado!!
Búscando casos malos:
Supongamos que el texto esta compuesto por 10 letras a:
aaaaaaaaaa
Y que nuestro patrón es baaaa. En este caso la fuerza bruta, gasta O(n) para decir que falló
la tabla siguiente BMH es:
|
|
|
|
|
|
BMH realiza la siguiente ejecución:
aaaaaaaaaa
baaaa
baaaa
baaaa
baaaa
baaaa
baaaa
Este es un peor caso para BMH O(m*n)!!
Búsqueda multipatrón en un texto
Cuando se desea buscar múltiples patrones en un texto utilizando el algoritmo BMH, se procede de la siguiente forma:
Tabla siguiente arma:
a->1, r->2, m->3, todas las demas son 0
Tabla siguiente rios:
r->1, i->2, o->3, todas las demas son 0
se venden armarios
a pedido
arma
rios
, fallan los dos patrones y en ninguno hay v => salto
completo
arma
rios
, fallan los dos patrones y en ninguno hay e => salto
completo
arma
rios
, fallan ambos, pero ambos tiene la r, luego el salto
menor es el que alinea la r de arma
arma
rios
, patrón arma encontrado!!