Z Algorithm calcula la Z-array en tiempo lineal: Z[i] es la longitud del substring más largo que comienza en i y es también un prefix del string completo.
Es una alternativa a KMP para pattern matching y suffix array construction, con la misma complejidad O(n+m) pero conceptualmente más simple: mantén una ventana [L,R] del substring que coincide con el prefix.
Cómo Funciona
- Inicializa
Z[0] = n(el string completo coincide consigo mismo). - Mantén ventana
[L,R]dondeS[L..R]coincide conS[0..R-L]. - Para cada
ide 1 an-1:- Si
i > R: calcula Z[i] por brute force desdei. - Si
i <= R: usa conocimiento previoZ[i-L].- Si
Z[i-L] < R-i+1:Z[i] = Z[i-L](dentro de la ventana). - Si no: recalcula desde
R+1y extiendeR.
- Si
- Si
- Matching: concatena
patrón + '$' + texto; buscaZ[i] == m.
Idea Clave
La ventana [L,R] codifica el substring más largo que coincide con el prefix y termina en R. Cuando estás dentro de la ventana (i <= R), ya sabes que S[i..R] coincide con S[i-L..R-L], por lo que Z[i] está al menos garantizado hasta R-i+1.
Si Z[i-L] es menor que R-i+1, el match está completamente dentro de la ventana y lo copias. Si no, necesitas extender R manualmente desde R+1.
Ejemplo Trabajado
String: ABABAB, n = 6.
Construcción de Z-array:
i=0: Z[0]=6 (por definición), L=0, R=5
i=1: i > R? No (1 <= 5). Z[1]=Z[0]=6, pero Z[0] >= R-i+1=5 → extiende desde R+1=6, fin. Z[1]=0.
i=2: i > R? Sí. Calcula brute force: S[2..]='ABAB' vs S[0..]='ABABAB' → 4 coinciden. Z[2]=4. L=2, R=5.
i=3: i <= R=5. Z[3]=Z[3-2]=Z[1]=0 < R-i+1=3 → Z[3]=0.
i=4: i <= R=5. Z[4]=Z[4-2]=Z[2]=4 >= R-i+1=2 → extiende desde 6, fin. Z[4]=2. L=4, R=5.
i=5: i <= R=5. Z[5]=Z[5-4]=Z[1]=0 < R-i+1=1 → Z[5]=0.
Z-array: [6, 0, 4, 0, 2, 0].
Pattern matching: ABC$ABABAB → busca Z[i]=3 (longitud de ABC).
Casos Extremos y Trampas
- Todos caracteres iguales —
AAAAAA: Z =[6,5,4,3,2,1], la ventana se expande cada vez. - Sin repeticiones —
ABCDEF: Z =[6,0,0,0,0,0], sin Z-box útil. - Z[0] — por definición es
n, pero para matching ignoramos índice 0. - Empty string — indefinido; retorna array vacío.
Comparación con KMP
| Aspecto | Z Algorithm | KMP |
|---|---|---|
| Preprocessing | Z-array del texto completo | LPS table del patrón |
| Matching | Busca Z[i] == m | Comparación carácter por carácter |
| Complejidad | O(n+m) | O(n+m) |
| Concepto | Ventana prefix-suffix | Prefix function |
Aplicaciones
- Pattern matching — alternativa a KMP
- Suffix array construction — base para algoritmos más avanzados
- String periodicity — encontrar el periodo mínimo de un string
- Enseñanza — introduce Z-box y ventanas deslizantes
Trayectoria de Práctica
- Implementa Z-array; traza
ABABAByAAAAAA. - Implementa pattern matching con
patrón$texto. - Compara con KMP: ¿cuál es más fácil de implementar?
- Investiga Z-algorithm para suffix arrays: ¿cómo ordena sufijos?
- ¿Por qué
Z[0]=nno se usa para matching?