Saltar al contenido
Portada » Algoritmo Z para detectar patrones

Algoritmo Z para detectar patrones

El algoritmo Z encuentra todas las ocurrencias de un patrón en un texto en tiempo lineal. Siendo la longitud del texto n y la longitud del patrón m, la complejidad es O(n + m), lineal. Se puede observar que la complejidad es la misma que el algoritmo KMP, sin embargo el algoritmo Z es más sencillo de entender. Todo parte de la construcción del array Z.

Qué es el Array Z

Para un String str[0..n-1], su array Z tiene la misma longitud. Un elemento Z[i] del array Z almacena la longitud de la sub-cadena más larga empezando por str[i]. La primera entrada del array Z tiene menos peso ya que que el String completo es un prefijo de si mismo. Ejemplo:

Índice            0   1   2   3   4   5   6   7   8   9  10  11 
Texto             a   a   b   c   a   a   b   x   a   a   a   z
Valores Z         X   1   0   0   3   1   0   0   2   2   1   0
str = "aabaacd"
Z[] = {x, 1, 0, 2, 1, 0, 0}

Algoritmo Z y complejidad lineal

La idea es concatenar patrón y texto y generar una cadena “P$T”. Donde P es el patrón a encontrar y $ es un carácter especial que no debe estar presente en el patrón ni en el texto, y T es el texto. En el array Z, si el valor Z en cualquier punto es igual a la longitud del patrón, entonces el patrón está presente en ese punto. Ejemplo:

Patron P = "aab",  Texto T = "baabaa"

Cadena concatenada = "aab$baabaa"

Array Z para la cadena concatenada = {x, 1, 0, 0, 0, 
                                          3, 1, 0, 2, 1}.
Como la longitud del patrón es 3, el valor 3 del array Z indica la presencia del patrón 
 

Como construir el array Z

Una solución sencilla para construirlo es con dos bucles anidados. El bucle exterior recorre todos los índices y el bucle interno encuentra la longitud del prefijo más largo que coincide con la sub-cadena empezando por el índice actual. La complejidad de esta solución es de O(n2).

Implementación Java


class DeteccionPatronesZ {

	public static void busqueda(String texto, String patron)
	{

		// Crear la cadena concatenada "P$T"
		String concatenado = patron + "$" + texto;

		int longitud = concatenado.length();

		int Z[] = new int[longitud];

		// Construye el array Z
		obtenerArrayZ(concatenado, Z);

		// iteramos sobre el array Z
		for(int i = 0; i < longitud; ++i){

			// si Z[i] es igual a la longitud del patron, lo tenemos identificado
		
			if(Z[i] == patron.length()){
				System.out.println("Patron encontrado en el indice "
							+ (i - patron.length() - 1));
			}
		}
	}


	private static void obtenerArrayZ(String cadena, int[] Z) {

		int n = cadena.length();

		int L = 0, R = 0;

		for(int i = 1; i < n; ++i) {

			if(i > R){

				L = R = i;

				// R-L = 0 al inicio, empezara comprobando desde el indice 0. 
                                // Por ejemplo, para "ababab" e i=1, el valor de R
				// permanece 0 y Z[i] se vuelve 0. Para la cadena "aaaaaa"
				// e i=1, Z[i]y R valen 5.

				while(R < n && cadena.charAt(R - L) == cadena.charAt(R))
					R++;
				
				Z[i] = R - L;
				R--;

			}
			else{

				int k = i - L;

	
				// Por ejemplo, cadena= "ababab", i = 3, R = 5
				// y L = 2
				if(Z[k] < R - i + 1)
					Z[i]=Z[k];

				else{

					L = i;
					while(R < n && cadena.charAt(R - L)==                        cadena.charAt(R))
						R++;
					
					Z[i]= R-L;

					R--;
				}
			}
		}
	}
	
	public static void main(String[] args)
	{
		String texto = "pruebas y mas pruebas";
		String patron = "prueba";

		search(texto, patron);
	}
}

Más algoritmos de ordenación y búsqueda

AsuntoDescripción
Ordenación BurbujaOrdenación algoritmo BubbleSort.
Ordenación InserciónAlgoritmo de ordenación por inserción
Ordenación SelecciónAlgoritmo de ordenación por selección
Ordenación QuicksortAlgoritmo de ordenación eficiente Quicksort
Búsqueda BinariaAlgoritmo de búsqueda binaria
Patrones: Algoritmo ZDetección de patrones con algoritmo Z
Patrones: Algoritmo NaiveDetectar patrones con algoritmo ingenuo o naive
Algoritmo de Dijkstra Como encontrar el camino más corto entre dos nodos en un grafo ponderado
Algoritmo de KruskalSe utiliza para encontrar el árbol de expansión mínimo en un grafo ponderado

Recursos básicos Java

AsuntoDescripción
Tutorial básico y sintaxisTutorial básico Java y sintaxis. Aprende los fundamentos del lenguaje.
Hilos (Threads)Aprende a manejar hilos y las cuestiones básicas de la concurrencia
Funciones LambdaAquí te enseñamos las nociones más importantes para arrancas con funciones lambda
PalíndromosPrograma de ejemplo para el uso de palíndromos en Java.
Máquina Virtual de JavaTe explicamos el funcionamiento de la máquina virtual de java (Java Virtual Machine – JVM)
JDK, JRE y JVMDiferencias entre el JDK, JRE y JVM.
Mejores libros Java en EspañolHazte con los mejores libros Java para aprender paso a paso y profundizar en las mejores prácticas
TensorFlowManejo del API de TensorFlow para la construcción de grafos de operaciones y su ejecución
Tutorial Log4jTutorial para el manejo de Log4j, herramienta ágil y flexible para la gestión de Logs en Java
Java SecurityEntiende y aplica las posibilidades que da Java para mantener la seguridad
Tutorial JConsoleAprende los conceptos básicos de monitorización de procesos Java con JConsole
JavaFXTutorial de JavaFX, librería gráfica moderna para construcción de GUIs en móvil, escritorio y web.
Estructuras de datos en JavaExplicación y ejemplos de las estructuras de datos más importantes: listas, pila, cola, arbol.
JavaapiConjunto de clases, interfaces, métodos y paquetes que forman parte de la plataforma Java estándar
Algoritmo HuffmanMétodo eficiente para codificar datos, asignando códigos más cortos a los caracteres más frecuentes