El algoritmo más rápido para encontrar la subsecuencia de palíndromo más larga

8

Antes que nada debemos leer una palabra y el tamaño deseado.
Luego, necesitamos encontrar el palíndromo más largo creado por los caracteres en esta palabra utilizada en orden.
Por ejemplo, para size = 7 y word = "abcababac" la respuesta es 7 ("abababa").

Postdata: el tamaño de la palabra es menor que 3000.

Gilles 'SO- deja de ser malvado'
fuente
Con max palindrome, ¿quiere decir que puede eliminar caracteres de la cadena para dejar un palindrome y desea el palindrome más largo (o la eliminación mínima)?
1
En su ejemplo, también hay cababac de longitud 7. Los caracteres eliminados se encuentran uno al lado del otro y al final. ¿Se le permite alguna de estas restricciones? Simplifican enormemente la búsqueda.
66
Esto ya fue respondido en Stack Overflow: ¿cómo encontrar la subsecuencia palindrómica más larga?
@GenericHuman: La mejor respuesta en esa pregunta fue buena para el capítulo del libro de texto que estaba leyendo el autor de la pregunta. No es una buena respuesta para este autor de la pregunta. Vea esta pregunta: stackoverflow.com/questions/7043778/… en su lugar.
Neil G
1
¿Cómo se usa el tamaño? Dices que quieres el "palíndromo máximo", entonces, ¿qué pasa si el palíndromo más largo es más largo o más corto que el tamaño dado?
Gilles 'SO- deja de ser malvado'

Respuestas:

6

Hay un algoritmo que lleva el nombre del algoritmo de Manacher, que es realmente rápido, un algoritmo de tiempo lineal.

Ver la referencia de Wikipedia


Postdata: Si está realmente familiarizado con el Algoritmo Z , encontrará que son similares.


Editar

Acabo de entender mal el significado del OP (pero no quiero eliminar la información del procedimiento. Es algo útil). Se refiere a la subsecuencia de palíndromo más larga de una cadena, por lo que la programación dinámica parece buena:

fj,k=max(fj,k+1,fj+1,k,2[Sj=Sk]+fj+1,k1),j<kfk,k=1fj,k=0,j>k
dónde Fj,k denota la longitud de la subsecuencia de palíndromo más larga de Sj..ky [PAGS]es el soporte de Iverson , creo que es como LCS .
Yai0Phah
fuente
44
Estás respondiendo en el caso de la subcadena, pero la pregunta es sobre subsecuencias.
¿No debería ser el primer término f (j, k-1)?
Abhishek Bansal
5

El algoritmo más rápido que se me ocurre es aplicar LCS de manera creativa. Puede resolver este problema en O (N ^ 2) tiempo y O (N ^ 2) espacio donde N es el tamaño de la cadena.

LCS (S, reverse (S)) le dará la subsecuencia palindrómica más grande, ya que la subsecuencia palindrómica más grande será la subsecuencia común más grande entre la cadena S y su reverso.

Por ejemplo,
S = "abcababac"
T = "cababacba" (reverso de S)
LCS (S, T) = "abababa"

Shashwat
fuente
¿Puede argumentar que este algoritmo es el más rápido que alguien puede tener, como se hace la pregunta?
Juho
@Juho: no puedo. :( Este es el algoritmo más rápido que conozco. Sin embargo, fue aceptado en el juez en línea de UVA ( uva.onlinejudge.org/external/114/11404.html ) y en ACM las restricciones del problema son tales que solo pasará la solución optimizada. por lo tanto la solución es lo suficientemente rápido, no está seguro sobre el más rápido.
Shashwat
2

El problema de encontrar LPS de una cadena se puede convertir en encontrar la subsecuencia común más larga de dos cadenas. En esto, una cadena será la original y la segunda será inversa a la cadena original.

El problema de la subsecuencia común más larga es como el problema de coincidencia de patrones, excepto que puede omitir caracteres en el texto. Además, el objetivo es devolver solo un partido, que es el mayor tiempo posible.

LCS se puede resolver en O(n2) utilizando recursividad y memorización.

Existe un algoritmo ligeramente más rápido descubierto por Masek y Paterson de complejidad temporal O(n2/lgn). Enlace de papel: Masek y Paterson

Otros dos algoritmos presentados por Hirschberg para calcular LCS de dos cadenas A (Talla n) y B (Talla m) Basado en el supuesto de que los símbolos que pueden aparecer en estas cadenas provienen de algún alfabeto de tamañot(eso es realmente cierto en la mayoría de los casos). Entonces los símbolos se pueden almacenar en la memoria usandolog(t)bits, que caben en una palabra de memoria. dos símbolos se pueden comparar enO(1)hora. Número de diferentes en cadenaB se denota por s, que por supuesto es menor que ambos m y t.

  1. Este requiere O(pn+nlgn) tiempo donde pes la longitud de LCS. Esto se usa cuando se espera que la longitud de LCS sea pequeña. Cuando resolvemos este problema usando la programación dinámica, encontramos que la mayoría de las entradas en la matriz son iguales, por lo que podemos usar la idea de la programación dinámica dispersa.

  2. Este algoritmo requiere O(p(m+1p)logn)hora. Esto es muy eficiente cuando la longitud de LCS está cerca dem, en ese caso estará cerca de O(nlgn).

Los procedimientos y algoritmos detallados se explican en el artículo de Hirschberg .

Sohel Rahman propone otro buen algoritmo que se ejecuta en O(Rloglogn) tiempo, donde Res el número total de pares de posiciones ordenadas en las que las cadenas coinciden. No es aplicable cuandoR es el orden de O(n2), pero hay muchos casos cuando R es el orden de n. Éste utiliza el concepto RMQ (consulta de rango máximo). Enlace de papel: Rahman

Surendra
fuente
@ Frankie, gracias! He editado la respuesta. Ahora los enlaces son visibles.
Surendra
Aún faltaba su formato; por favor revise mi edición para ver qué es posible. Las referencias del artículo siguen siendo malas porque dependen del enlace que siempre funciona, para siempre. Ver aquí para consejos; título, autores y año deben ser dados (al menos).
Raphael
Dos preocupaciones con lo que escribe: 1) "requiere O()"no tiene sentido (ya que Oda límites superiores ), e ignorando que probablemente sea incorrecto; Supongo que muestran los límites superiores de estas órdenes, pero los algoritmos pueden ser incluso más rápidos. 2) Al menos en el último párrafo, quieresΩ(n2).
Raphael
-1

Probablemente me estoy perdiendo algo, porque me parece bastante trivial: intenta emparejar cada personaje con un personaje igual. Luego coloque el primer carácter de cada par en el lado izquierdo, el otro carácter en el lado derecho, y si quedan caracteres (es decir, caracteres no emparejados con otro), luego elija uno de ellos y póngalo en el medio.


fuente
1
Cuando tengas aubvawb (con u,v,w palabras), ¿cómo decidiría si el primer y último carácter del palíndromo debería ser a o b? Necesita examinar el contenido deu,v,wantes de tomar una decisión si quieres tener el palíndromo más largo.