Encontrar la subsecuencia repetitiva más larga

9

Dada una cadena s , me gustaría encontrar la subsecuencia de repetición más larga (al menos dos veces). Es decir, me gustaría encontrar una cadena que sea una subsecuencia (no tiene que ser contigua) de tal que . Es decir, es una cadena cuyas mitades aparecen dos veces seguidas. Tenga en cuenta que es una subsecuencia de , pero no necesariamente una subcadena.wsw=wwwws

Ejemplos:

Para 'ababccabdc' será 'abcabc', porque 'abc' = 'abc' y 'abc' aparecen (al menos) dos veces en 'ababccabdc'.

Para 'addbacddabcd' una opción es 'dddd' porque 'dd' aparece dos veces (no puedo usar la misma letra varias veces, pero aquí tengo 4 'd's así que está bien), pero es de longitud 4. Puedo encontrar una mejor de longitud 8: 'abcdabcd', porque 'abcd' es una subcadena de 'addbacddabcd' que aparece dos veces.

Estoy interesado en encontrar la subsecuencia repetitiva más larga. Esto también se llama "encontrar el cuadrado más largo / más grande", pero he leído muchos artículos en los que se define un cuadrado para una subcadena y no para una subsecuencia.

Puedo usar fácilmente un algoritmo de fuerza bruta que tomará iterando en todas las opciones para un punto de interrupción en la cadena, y luego tendré dos cadenas en las que buscaré la subsecuencia común más grande / más larga, pero cada verificación tomará O ( n 2 ) utilizando una técnica de programación dinámica, por lo que todo el tiempo será O ( n 3 ) . Encontré un algoritmo más eficiente para la subsecuencia común más larga que toma , por lo que el tiempo de ejecución será .O(n3)O(n2)O(n3)O(n2logn)O(n3logn)

Estoy buscando un algoritmo más eficiente para el problema de subsecuencia repetitiva más largo. Quizás mi idea de iterar sobre todos los puntos de interrupción desperdicia demasiado tiempo y puede reducirse a menos iteraciones. O quizás un algoritmo con una actitud diferente pueda resolver este problema.

He buscado en muchas revistas y preguntas anteriores, y la mayoría de los resultados que encontré fueron sobre una subcadena y no sobre una subsecuencia.

También he leído que esto se puede hacer usando árboles de sufijos, pero esto también era relevante para las subcadenas y no estoy seguro de si esa idea puede extenderse para la subsecuencia.

Estoy buscando una solución que se ejecute en el tiempoO(n2) . Si existe uno en el tiempo eso será aún mejor (no estoy seguro de si existe).O(nlogn)

Dan D-man
fuente
44
Busque árboles de sufijos o matrices de sufijos.
Seudónimo
1
Es muy poco probable que exista un algoritmo de tiempo para este problema, ya que si lo hiciera, podría usarlo para vencer al algoritmo más conocido para encontrar el LCS de dos cadenas de longitud n u y v de la siguiente manera: Forma la cadena x u x v , donde x es n + 1 copias de un carácter que no aparece en u o v , y luego ejecuta su o ( n 2 )o(n2)nuvxuxvxn+1$uvo(n2)algoritmo de tiempo en él. Ambas "mitades" de la subsecuencia repetitiva más larga necesariamente comenzarán con , por lo que la mitad proviene de cada uno de u y v , resolviendo el problema de LCS. xuv
j_random_hacker
@j_random_hacker LCS podría resolverse en usando Suffix Tree o en O ( n log n ) usando hashes rodantes. O(norte+metro)O(norteIniciar sesiónnorte)
Evil
@ Mal: ​​todavía no veo cómo, ¿podrías dar un poco más de detalles? (¿Está seguro de que no está pensando en Sub común más larga cadena , que puede ser resuelto en esas complejidades de tiempo?)
j_random_hacker
@j_random_hacker Pensé que estaba comparando el objetivo con LCS (consecutivo), pero aquí, como mencionó, sí, ni siquiera he visto una solución funcional en n ^ 2 para la subsecuencia común más larga (he encontrado una código de programación dinámico, propagado a través de muchas páginas, que es defectuoso, similar a la respuesta con voto negativo). Así que simplemente no entendí tu comentario, lo siento. o(n2)
Evil

Respuestas:

-1

Aquí hay una solución de programación dinámica.

Suponga que la cadena de entrada es . Cree una tabla T cuyas filas y columnas estén indexadas por 0 , ... , n (donde n es la longitud de la cadena), poblada por la regla T [ i , j ] = { 0 si  i = 0  o  j = 0 , T [ i - 1 , j - 1 ] + 1 si  x iX1...XnorteT0 0,...,nortenorte La respuesta esT[n,n].

T[yo,j]={0 0Si yo=0 0 o j=0 0,T[yo-1,j-1]+1Si Xyo=Xj y yoj,max(T[yo-1,j],T[yo,j-1])de otra manera.
T[norte,norte]
jir17
fuente
Supongamos que estamos en algún con i = j + 1 , y la condición en su declaración es verdadera. Entonces implica que el carácter en la posición i - 1 = j es parte de ambas subsecuencias. yo,jyo=j+1ifdp[i][j] = dp[i - 1][j - 1] + 1yo-1=j
j_random_hacker
3
Bienvenido a la informática! Deshágase del código fuente y reemplácelo con ideas, pseudocódigo y argumentos de corrección. Ver aquí y aquí para meta discusiones relacionadas.
Raphael
@Raphael Una fórmula recursiva no cuenta como código fuente.
Número945
1
@BreakingBenjamin Dependiendo de su idioma de elección, puede escribir la recurrencia dada más o menos literalmente. El punto es que no hay explicación aquí.
Raphael