Étant donné une liste de chaînes, s_0, s_1, ..., s_n
recherchez la chaîne la plus courte S
qui contient chacune s_0, s_1, ..., s_n
comme sous - chaîne .
Exemples :
S('LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE')='SEDOLOREMAGNAD'
S('ABCDE', 'BCD', 'C')='ABCDE'
Écrivez le programme (ou la fonction) le plus court qui résout ce problème. Vous pouvez représenter des chaînes sous forme de tableaux ou de listes de caractères / entiers si vous le souhaitez. Les bibliothèques standard sont OK. Pour l'entrée / sortie, vous pouvez utiliser ce qui est plus pratique: STDIN / STDOUT, invite de l'utilisateur, paramètre / valeur de retour d'une fonction, etc.
Les performances ne sont pas critiques - disons, pour une entrée de longueur totale <100 caractères, le résultat doit être calculé en <10 secondes en moyenne sur un matériel moderne.
Réponses:
Python 2,
170153/157/159Raccourci grâce à certaines des idées de Baptiste .
Le deuxième saut de ligne n'est pas nécessaire.
Entrée:
'LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE'
Sortie:
SEDOLOREMAGNAD
Même avec de longues chaînes d'entrée, cela s'exécute en moins de 2 secondes s'il y a au plus 7 chaînes d'entrée (comme c'est le cas dans l'exemple donné, qui s'exécute en
1,71,5 seconde sur ma machine). Avec 8 chaînes d'entrée ou plus, cependant, cela prend plus de 10 secondes, car la complexité temporelle estO(n!)
.Comme l'a souligné Baptiste,
range(99)
doit être remplacé parrange(len(w))
si des longueurs d'entrée arbitraires doivent être prises en charge (ce qui fait la longueur totale du code 157 caractères). Si des chaînes d'entrée vides doivent être prises en charge, elles doivent être remplacées parrange(len(w)+1)
. Je pense querange(99)
fonctionne correctement pour toute longueur d'entrée totale inférieure à 200, cependant.Plus de tests:
la source
Mathematica
337 418372Après avoir essayé sans succès d'implémenter à l'aide de Mathematica
LongestCommonSubsequencePositions
, je me suis tourné vers la correspondance de modèles.La règle de correspondance de motifs,
prend une paire ordonnée de mots (représentés sous forme de listes de caractères) et renvoie: (1) les mots,
{a,y}
et{y,b}
suivi par (2) la sous - chaîne commune,y
qui relie l'extrémité d'un mot avec le début de l'autre mot, et, enfin, le mot combiné{a,y,b}
qui remplacera les mots d'entrée. Voir Belisarius pour un exemple connexe: /mathematica/6144/looking-for-longest-common-substring-solutionTrois caractères de soulignement consécutifs signifient que l'élément est une séquence de zéro ou plusieurs caractères.
Reverse
est utilisé plus tard pour garantir que les deux commandes sont testées. Les paires qui partagent des lettres pouvant être liées sont retournées inchangées et ignorées.Modifier :
Ce qui suit supprime de la liste les mots qui sont "enterrés" (c'est-à-dire entièrement contenus) dans un autre mot (en réponse au commentaire de @ flornquake).
Exemple :
résultats
Usage
la source
"LOREM", "ORE", "R"
?"LOREM"
?)GolfScript, 66 caractères
Assez court, mais en raison de la complexité temporelle exponentielle (et GolfScript) très lent, il casse le délai de 10 secondes.
Exemples:
la source
Python 2,
203187200Entrée:
['LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE']
Sortie:
SEDOLOREMAGNAD
modifier
À l'aide de
reduce
quelques trucs importés, je peux réduire cela davantage (et à une seule ligne!):Modifier 2
Comme l'a noté le tremblement de terre, cela donne des résultats incorrects lorsqu'un mot est contenu dans un autre. La correction pour cela ajoute 13 autres caractères:
Voici la version nettoyée:
Il est possible de raser quelques caractères au détriment de l'exactitude théorique en utilisant à la
range(99)
place derange(len(x))
(crédits au tremblement de terre pour avoir pensé à celui-ci).la source
'LOREM', 'ORE', 'R'
produit incorrectement la sortieLOREMORER
.Python, 144 caractères
S
prend un ensemble de motsA
qui doivent encore être placés et une chaînes
contenant des mots placés jusqu'à présent. Nous choisissons un mot restanta
deA
et le chevauchons de0
à deslen(a)
caractères avec la fin des
.Prend seulement environ 0,15 seconde sur l'exemple donné.
la source
['LOREM', 'ORE', 'R']
. J'ai pris la liberté de résoudre ce problème et de jouer un peu plus à votre solution: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
(une deuxième ligne n'est pas nécessaire). Utilisation:S({'LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE'})
retourne'SEDOLOREMAGNAD'
.Haskell, 121
Moins deux si la fonction n'a pas besoin d'être liée à un nom
la source