Dada una lista de cadenas, s_0, s_1, ..., s_n
encuentre la cadena más corta S
que contenga cada una de ellas s_0, s_1, ..., s_n
como una subcadena .
Ejemplos :
S('LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE')='SEDOLOREMAGNAD'
S('ABCDE', 'BCD', 'C')='ABCDE'
Escriba el programa (o función) más corto que resuelva este problema. Puede representar cadenas como matrices o listas de caracteres / enteros si lo desea. Las bibliotecas estándar están bien. Para entrada / salida, puede usar lo que sea más conveniente: STDIN / STDOUT, indicador de usuario, parámetro / valor de retorno de una función, etc.
El rendimiento no es crítico, digamos, para una entrada de longitud total <100 caracteres, el resultado debe calcularse en <10 segundos en promedio de hardware moderno.
Respuestas:
Python 2,
170153/157/159Acortado gracias a algunas de las ideas de Baptiste .
El segundo salto de línea no es necesario.
Entrada:
'LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE'
Salida:
SEDOLOREMAGNAD
Incluso con cadenas de entrada largas, esto se ejecuta en menos de 2 segundos si hay como máximo 7 cadenas de entrada (como es el caso en el ejemplo dado, que se ejecuta en
1.71.5 segundos en mi máquina). Sin embargo, con 8 o más cadenas de entrada, lleva más de 10 segundos, ya que la complejidad del tiempo esO(n!)
.Como Baptiste señaló,
range(99)
debe reemplazarserange(len(w))
si se deben admitir longitudes de entrada arbitrarias (lo que hace que la longitud total del código sea de 157 caracteres). Si se deben admitir cadenas de entrada vacías, debe cambiarse arange(len(w)+1)
. Sinrange(99)
embargo, creo que funciona correctamente para cualquier longitud de entrada total inferior a 200.Más pruebas:
fuente
Mathematica
337 418372Después de intentar implementar sin éxito usando Mathematica's
LongestCommonSubsequencePositions
, recurrí a la coincidencia de patrones.La regla de coincidencia de patrones,
toma un par de palabras ordenadas (representadas como listas de caracteres) y devuelve: (1) las palabras,
{a,y}
y{y,b}
seguido de (2) la subcadena comúny
, que vincula el final de una palabra con el comienzo de la otra palabra, y finalmente, la palabra combinada{a,y,b}
que reemplazará las palabras de entrada. Ver Belisarius para un ejemplo relacionado: /mathematica/6144/looking-for-longest-common-substring-solutionTres caracteres de subrayado consecutivos significan que el elemento es una secuencia de cero o más caracteres.
Reverse
se emplea más tarde para garantizar que ambas órdenes se prueben. Los pares que comparten letras enlazables se devuelven sin cambios e ignorados.Editar :
Lo siguiente elimina de la lista las palabras que están "enterradas" (es decir, totalmente contenidas) en otra palabra (en respuesta al comentario de @ flornquake).
Ejemplo :
devoluciones
Uso
fuente
"LOREM", "ORE", "R"
?"LOREM"
?)GolfScript, 66 caracteres
Bastante corto, pero debido a la complejidad de tiempo exponencial (y GolfScript) realmente lento, rompe el límite de tiempo de 10 segundos.
Ejemplos:
fuente
Pitón 2,
203187200Entrada:
['LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE']
Salida:
SEDOLOREMAGNAD
Editar
Utilizando
reduce
algunos trucos de importación sucios, puedo reducir esto aún más (¡y solo a una línea!):Editar 2
Como notó flornquake, esto da resultados incorrectos cuando una palabra está contenida en otra. La solución para esto agrega otros 13 caracteres:
Aquí está la versión limpiada:
Es posible eliminar algunos caracteres a costa de la corrección teórica usando en
range(99)
lugar derange(len(x))
(créditos para flornquake por pensar en este).fuente
'LOREM', 'ORE', 'R'
produce incorrectamente la salidaLOREMORER
.Python, 144 caracteres
S
toma un conjunto de palabrasA
que aún necesitan colocarse y una cadena ques
contiene palabras colocadas hasta ahora. Escogemos una palabra restantea
deA
y la superposición desde0
alen(a)
personajes con el final des
.Solo toma alrededor de 0.15 segundos en el ejemplo dado.
fuente
['LOREM', 'ORE', 'R']
. Me he tomado la libertad de arreglar eso y poner a prueba tu solución un poco más:S=lambda A,s='':A and min((S(A-{a},(s+a[max(i*(s[-i:]==a[:i])for i in range(len(a))):],s)[a in s])for a in A),key=len)or s
(no se necesita una segunda línea). Uso:S({'LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE'})
devoluciones'SEDOLOREMAGNAD'
.Haskell, 121
Menos dos si la función no necesita estar vinculada a un nombre
fuente