Árbol palíndromo

árbol palíndromo
inglés  árbol

árbol palíndromo para cuerda eertree
Tipo de estructura de datos
año de invención 2015
Autor Mijaíl Rubinchik [d]
Complejidad en los símbolos O
Lo peor
Edificio
Consumo de memoria
 Archivos multimedia en Wikimedia Commons

Un árbol palindrómico ( eng.  palindromic tree , también overtree [1] , ing.  eertree ) es una estructura de datos diseñada para almacenar y procesar subcadenas palindrómicas de una cadena . Fue propuesto por científicos de la Universidad Federal de los Urales Mikhail Rubinchik y Arseny Shur en 2015. Representa dos árboles de prefijos , ensamblados a partir de las "mitades" derechas de subcadenas palindrómicas de longitud par e impar, respectivamente. La estructura ocupa memoria y se puede construir en tiempo , donde  es la longitud de la cadena y  es el número de caracteres diferentes en ella. Con la ayuda de un árbol de palíndromos, se pueden resolver eficazmente problemas tales como contar el número de subcadenas palindrómicas diferentes, encontrar la división de una cadena en el menor número de palíndromos, verificar si una subcadena es un palíndromo y otros.

Notación

Sea  alguna cadena y  sea la cadena invertida . Al describir el árbol palíndromo de una cadena , se usa la siguiente notación [2] :

Estructura de árbol

En la notación anterior, el árbol palíndromo de una cadena  es un grafo dirigido , cada vértice del cual corresponde y se identifica con algún subpalíndromo único de la cadena. Si la cadena tiene subpalíndromos y , donde  es algún carácter alfabético , entonces el árbol de palíndromos tiene un arco marcado con el símbolo , desde el vértice correspondiente a , hasta el vértice correspondiente a . En tal gráfico, cualquier vértice puede tener solo un arco entrante. Por conveniencia, también se introducen dos vértices auxiliares, que corresponden a palíndromos de longitud ( cadena vacía ) y cadena ("imaginaria"), respectivamente. Los arcos de la cadena vacía conducen a vértices correspondientes a palíndromos de la forma , y de la “cadena imaginaria” a vértices correspondientes a palíndromos de la forma (es decir, que consisten en un solo carácter). Un vértice se llama incluso si tiene un palíndromo de longitud par, e impar en caso contrario. De la definición se sigue que los arcos en un árbol palíndromo pasan solo entre vértices con la misma paridad. Desde el punto de vista de los árboles de prefijos, esta estructura se puede describir de la siguiente manera [3] :

Los vértices y arcos del árbol palíndromo forman dos árboles de prefijos cuyas raíces se ubican en los vértices que definen las cadenas vacías e "imaginarias", respectivamente. En este caso, el primer árbol de prefijos está compuesto por las mitades derechas de subpalíndromos de longitud par, y la segunda de impares.

El número de vértices en el árbol palíndromo no excede , lo que es consecuencia directa del siguiente lema [4] :

Una cadena de longitud puede tener como máximo distintas subcadenas palindrómicas no vacías. Además, después de asignar un determinado carácter al final de una cadena, el número de subpalíndromos diferentes de esta cadena no puede aumentar más de .

Prueba

Esta afirmación se deriva de los siguientes hechos:

  1. Si un palíndromo es un sufijo de un palíndromo , entonces también es su prefijo;
  2. Si los palíndromos y son sufijos de la cadena y , entonces aparece al menos dos veces (como prefijo y como sufijo );
  3. Cualquier cadena puede tener como máximo un sufijo palíndromo único (que se presenta solo una vez).

La última propiedad es esencialmente equivalente al lema, ya que todas las nuevas subcadenas que aparecen al agregar el siguiente carácter a la cadena deben ser sus sufijos [5] .

Además de los arcos habituales que sirven como transiciones para el árbol de prefijos, para cada vértice del árbol de palíndromos se define un enlace de sufijos que conduce del vértice al vértice correspondiente al sufijo propio más grande (no igual a toda la cadena ). palíndromo _ Al mismo tiempo, el enlace del sufijo desde el vértice "imaginario" no está definido, pero por definición conduce de un vértice vacío al "imaginario". Los enlaces de sufijos forman un árbol con raíz en un vértice "imaginario" y juegan un papel importante en la construcción de un árbol palíndromo [3] .

Edificio

Como muchas otras estructuras de cuerdas, un árbol palíndromo se construye iterativamente . Inicialmente, consta solo de vértices correspondientes a las cadenas vacías e imaginarias. Luego, la estructura se reconstruye gradualmente a medida que la cadena crece un carácter a la vez. Dado que, como mucho, aparece un nuevo palíndromo en una cadena al agregar un carácter, reconstruir el árbol en el peor de los casos requerirá agregar un nuevo nodo y un enlace de sufijo. Para determinar un posible nuevo nodo durante la construcción del árbol, se mantiene un último puntero al nodo correspondiente al mayor de los sufijos palíndromo actuales [3] .

Todos los palíndromos de sufijo de la cadena son accesibles mediante enlaces de sufijo desde last , por lo que para determinar un nuevo palíndromo de sufijo (corresponderá al nuevo vértice, si lo hay) es necesario seguir los enlaces de sufijo de last hasta que se encuentre que el carácter que precede al sufijo-palindrome actual coincide con el carácter que se asignó a la cadena. Más formalmente,  sea el sufijo palíndromo máximo de la cadena , luego , o , donde  es algún sufijo palíndromo . Por lo tanto, iterando entre los enlaces de sufijo de last , se puede determinar si se puede expandir comparando los caracteres y . Cuando se haya encontrado el sufijo del palíndromo correspondiente , debe verificar si el árbol del palíndromo contiene una transición desde el vértice correspondiente mediante el símbolo [3] .

Si existe tal transición, entonces ya se ha encontrado en la línea anterior y corresponde al vértice al que conduce esta transición. De lo contrario, debe crear un nuevo vértice para él y hacer una transición desde . A continuación, defina un enlace de sufijo para que coincida con el segundo sufijo de palíndromo más largo . Para encontrarlo, uno debe continuar pasando por alto los últimos enlaces de sufijos hasta que se encuentre el segundo vértice , tal que ; es este vértice el que será el enlace del sufijo . Si denotamos la transición desde arriba con el símbolo , todo el proceso se puede describir con el siguiente pseudocódigo [3] :

función find_link(v): while s k -len(v)-1 ≠ s k : asignar v = link(v) devolver v función agregar_letra(c): asignar k = k + 1 definir s k = c definir q = encontrar_enlace(último) si δ(q, c) no está definido: definir p = nuevo_vértice() definir len(p) = len(q ) + 2 definir enlace(p) = δ(buscar_enlace(enlace(q)), c) definir δ(q, c) = p asignar último = δ(q, c)

Se supone aquí que inicialmente el árbol está descrito por solo dos vértices con longitudes y, en consecuencia, con un enlace de sufijo del primer vértice al segundo. La última variable almacena el vértice correspondiente al mayor palíndromo de sufijos de la línea actual, inicialmente apunta al vértice de la línea cero. También se supone que inicialmente es igual a y se escribe algún carácter de servicio, lo que no ocurre en la cadena .

Complejidad computacional

La complejidad del algoritmo puede variar según las estructuras de datos que almacenan la tabla de saltos en el árbol. En el caso general, cuando se usa una matriz asociativa , el tiempo empleado en acceder alcanza , donde  es el tamaño del alfabeto a partir del cual se construye la cadena. Vale la pena señalar que cada iteración de la primera llamada a find_link reduce la longitud de last , y de la segunda, la longitud de link(last) , que solo puede aumentar en uno entre llamadas sucesivas a add_letter . Por lo tanto, el tiempo total de find_link no excede y el tiempo total requerido para ejecutar llamadas add_letter se puede estimar como [3] . El consumo de memoria de esta estructura es lineal en el peor de los casos, sin embargo, si consideramos el tamaño medio de la estructura sobre todas las cadenas de una determinada longitud , el consumo medio de memoria será del orden de [6] .

Modificaciones

Simultáneamente con la introducción de esta estructura de datos, Rubinchik y Shur también propusieron una serie de modificaciones que permiten ampliar el alcance de las tareas resueltas por un árbol palíndromo. En particular, se propuso un método que permite construir un árbol palíndromo general para un conjunto de cadenas con las mismas asintóticas . Tal modificación nos permite resolver los mismos problemas considerados en el contexto de un conjunto de cadenas, por ejemplo, encontrar el subpalíndromo común más grande de todas las cadenas o el número de subpalíndromos diferentes de todas las cadenas en el agregado. Otra modificación propuesta fue una variante de construcción en árbol, en la que la adición de un carácter lleva tiempo en el peor de los casos (y no amortizado , como ocurre en la construcción estándar) y memoria. Este enfoque permite proporcionar persistencia parcial del árbol, en el que es posible revertir la adición del último carácter en momentos arbitrarios. Además, se propuso una versión totalmente persistente del árbol, que permite acceder y anexar un carácter a cualquiera de las versiones previamente guardadas en tiempo y memoria en el peor de los casos [7] .

En 2019, Watanabe y sus colegas desarrollaron una estructura de datos basada en un árbol palíndromo, llamado e 2 rtre 2 , para trabajar con subpalíndromos de cadenas dadas por codificación de longitud de ejecución [4] , y en 2020, el mismo equipo de autores, junto con Mieno, desarrolló dos algoritmos, que permiten mantener un árbol palíndromo en una ventana deslizante de tamaño . El primero de estos algoritmos requiere tiempo y memoria, y el segundo requiere tiempo y memoria [8] .

Aplicaciones

El árbol palíndromo ofrece muchas aplicaciones posibles para obtener algoritmos teóricamente rápidos y prácticamente fáciles de implementar para resolver una serie de problemas combinatorios en programación y cibernética matemática [9] .

Una de las tareas para las que se desarrolló esta estructura es contar diferentes subpalíndromos en una cadena en línea . Se puede configurar de la siguiente manera: un carácter a la vez se asigna un carácter a la vez a la cadena inicialmente vacía. En cada paso, debe imprimir el número de subpalíndromos diferentes en la cadena dada. Desde el punto de vista del árbol palíndromo, esto equivale a imprimir el número de vértices no triviales de la estructura en cada paso. En 2010 [10] se presentó una solución lineal para la versión fuera de línea de este problema , y ​​en 2013 [11] se encontró la solución óptima con tiempo de ejecución para la versión en línea . La solución indicada, sin embargo, utilizó dos estructuras de datos "pesadas": un análogo del algoritmo Manaker , así como un árbol de sufijos . El árbol palíndromo, por un lado, tiene las mismas asintóticas en el peor de los casos, y por otro lado, es una estructura mucho más ligera [3] .

Otra posible aplicación de esta estructura es la enumeración de cadenas binarias ricas en palíndromos [12] . Anteriormente se demostró que una palabra de longitud no puede contener más que diferentes palíndromos; las palabras en las que se logra esta estimación se denominan ricas en palíndromos. Amy Glen y sus colegas introdujeron el concepto de palabras ricas en palindrómicos en 2008 [13] . Rubinchik y Shur demostraron que usando un árbol de palíndromos, uno puede detectar todas las palabras ricas en palindrómicos cuya longitud no exceda , donde  es el número de tales palabras. Este resultado permitió aumentar el número de miembros conocidos de la secuencia A216264 en OEIS de 25 a 60. Los datos obtenidos mostraron que la secuencia crece mucho más lentamente de lo que se pensaba anteriormente, es decir, está acotada desde arriba como [14] .

Notas

  1. Rubinchik, 2016 , pág. 6-9
  2. Rubinchik, Shur, 2018 , págs. 1-2
  3. ↑ 1 2 3 4 5 6 7 Rubinchik, Shur, 2018 , págs. 2-6
  4. ↑ 1 2 Watanabe et al., 2019 , págs. 432-434
  5. Droubay et al., 2001 , págs. 542-546
  6. Rubinchik, Shur, 2016 , pág. una
  7. Rubinchik, Shur, 2018 , pág. 6-11
  8. Mieno et al., 2020
  9. Rubinchik, 2016 , pág. 75-76
  10. Groult, 2010
  11. Kosolobov et al., 2013
  12. Secuencia OEIS A216264 _
  13. Glen et al., 2009
  14. Rukavicka, 2017

Literatura

Enlaces