Knuth-Morris-Pratt (KMP) es un algoritmo de string matching que logra O(n + m) tiempo: n longitud del texto, m longitud del patrón. Lo logra preprocesando el patrón para crear una tabla LPS que indica cuánto puede “saltar” tras un mismatch.
A diferencia de la búsqueda naïve (que hace backtracking en el texto), KMP nunca retrocede en el texto: usa la LPS para reutilizar matches parciales.
Cómo Funciona
-
Preprocesa patrón para construir LPS:
lps[i]= longitud del longest proper prefix depat[0..i]que también es suffix.- Dos punteros
len(longitud prefix actual) yi(posición actual). - “Si
pat[len] == pat[i]:len++,lps[i] = len. - Si no y
len != 0:len = lps[len-1](salta). - Si no y
len == 0:lps[i] = 0.
-
Matching con dos punteros
i(texto) yj(patrón):- Si
text[i] == pat[j]:i++,j++. - Si
j == m: match encontrado. - Si mismatch y
j != 0:j = lps[j-1](salta en patrón). - Si mismatch y
j == 0:i++.
- Si
Idea Clave
La tabla LPS codifica la redundancia en el patrón. Cuando hay un mismatch en posición j, en vez de reiniciar el matching desde j=0, saltas a lps[j-1] porque ya sabes que los primeros lps[j-1] caracteres del patrón coinciden con el sufijo del texto actual.
Ejemplo: patrón ABABAC
ABABtiene prefixABy suffixAB→lps[3] = 2- Tras mismatch en
ABABAX, sabes queABya coincide, no reinicias desde cero.
Ejemplo Trabajado
Patrón: ABABAC, texto: ABABABAC.
Tabla LPS:
i=0 (A): len=0, no match, lps[0]=0
i=1 (B): len=0, A≠B, lps[1]=0
i=2 (A): len=0, A==A, len=1, lps[2]=1
i=3 (B): len=1, B==B, len=2, lps[3]=2
i=4 (A): len=2, A==A, len=3, lps[4]=3
i=5 (C): len=3, C≠B, len=lps[2]=1, C≠A, len=lps[0]=0, lps[5]=0
LPS = [0, 0, 1, 2, 3, 0].
Matching:
i=0,j=0: A==A →i=1,j=1i=1,j=1: B==B →i=2,j=2i=2,j=2: A==A →i=3,j=3i=3,j=3: B==B →i=4,j=4i=4,j=4: A==A →i=5,j=5i=5,j=5: B≠C,j=lps[4]=3i=5,j=3: B==B →i=6,j=4i=6,j=4: A==A →i=7,j=5i=7,j=5: C==C →i=8,j=6→ match en i=2
Resultado: match encontrado en índice 2 del texto.
Casos Extremos y Trampas
- Patrón repetitivo —
AAAAtiene LPS[0,1,2,3]; tras mismatch salta poco. - Patrón sin self-overlap —
ABCDtiene LPS[0,0,0,0]; salta a 0 tras mismatch. - Múltiples matches — KLS encuentra todos los matches; usa
lps[j-1]para continuar. - Edge case vacío — patrón
""no tiene sentido; texto""no tiene matches.
Comparación
| Algoritmo | Tiempo | Espacio | Backtrack texto |
|---|---|---|---|
| Naive | O(nm) | O(1) | Sí |
| KMP | O(n+m) | O(m) | No |
| Rabin-Karp | O(n+m) avg | O(1) | No |
| Boyer-Moore | O(n/m) best | O(m) | No |
Aplicaciones
- Editores de texto — find/replace, syntax highlighting
- Detección de plagio — búsqueda de patrones en documentos
- Bioinformática — búsqueda de secuencias en ADN
- Seguridad — detección de firmas en tráfico de red
Trayectoria de Práctica
- Implementa construcción de LPS; traza
ABABACyAAAA. - Implementa KMP matching; traza el ejemplo paso a paso.
- Compara con naive: cuenta comparaciones en un texto de 1000 chars.
- Investiga Z-algorithm: ¿por qué es equivalente a LPS?
- Investiga Boyer-Moore: ¿cuándo es mejor que KMP?
”