Dada uma lista de seqüências de caracteres, s_0, s_1, ..., s_n
encontre a menor S
que contém cada s_0, s_1, ..., s_n
uma como uma substring .
Exemplos :
S('LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE')='SEDOLOREMAGNAD'
S('ABCDE', 'BCD', 'C')='ABCDE'
Escreva o programa (ou função) mais curto que resolve esse problema. Você pode representar seqüências de caracteres como matrizes ou listas de caracteres / números inteiros, se desejar. Bibliotecas padrão estão OK. Para entrada / saída, você pode usar o que for mais conveniente: STDIN / STDOUT, prompt do usuário, parâmetro / valor de retorno de uma função etc.
O desempenho não é crítico - digamos, para uma entrada de comprimento total <100 caracteres, o resultado deve ser calculado em <10 segundos, em média, no hardware moderno.
Respostas:
Python 2,
170153/157/159Encurtado graças a algumas das idéias de Baptiste .
A segunda quebra de linha não é necessária.
Entrada:
'LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE'
Saída:
SEDOLOREMAGNAD
Mesmo com longas seqüências de entrada, isso é executado em menos de 2 segundos se houver no máximo 7 seqüências de entrada (como é o caso do exemplo dado, que é executado em
1,71,5 segundos na minha máquina). Com 8 ou mais seqüências de entrada, no entanto, leva mais de 10 segundos, já que a complexidade do tempo éO(n!)
.Como Baptiste apontou,
range(99)
precisa ser substituído porrange(len(w))
se comprimentos de entrada arbitrários devem ser suportados (tornando o comprimento total do código 157 caracteres). Se cadeias de entrada vazias devem ser suportadas, ela deve ser alterada pararange(len(w)+1)
. Eu acho querange(99)
funciona corretamente para qualquer comprimento total de entrada inferior a 200, no entanto.Mais testes:
fonte
Mathematica
337 418372Depois de tentar implementar sem sucesso usando o Mathematica
LongestCommonSubsequencePositions
, virei para a correspondência de padrões.A regra de correspondência de padrões,
pega um par ordenado de palavras (representado como lista de caracteres) e retorna: (1) as palavras
{a,y}
e{y,b}
seguido por (2) a substring comumy
, que vincula o final de uma palavra ao início da outra palavra e, finalmente, a palavra combinada{a,y,b}
que substituirá as palavras de entrada. Consulte Belisarius para obter um exemplo relacionado: /mathematica/6144/looking-for-longest-common-substring-solutionTrês caracteres de sublinhado consecutivos significam que o elemento é uma sequência de zero ou mais caracteres.
Reverse
é empregado posteriormente para garantir que os dois pedidos sejam testados. Os pares que compartilham letras vinculáveis são retornados inalterados e ignorados.Editar :
O texto a seguir remove da lista as palavras "enterradas" (ou seja, totalmente contidas) em outra palavra (em resposta ao comentário de @ flornquake).
Exemplo :
retorna
Uso
fonte
"LOREM", "ORE", "R"
?"LOREM"
?)GolfScript, 66 caracteres
Muito curto, mas devido à complexidade de tempo exponencial (e ao GolfScript) muito lento, ele quebra o limite de 10 segundos.
Exemplos:
fonte
Python 2,
203187200Entrada:
['LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE']
Saída:
SEDOLOREMAGNAD
Editar
Usando
reduce
e alguns truques de importação sujos, posso reduzir ainda mais isso (e apenas para uma linha!):Editar 2
Como observou Flornquake, isso fornece resultados incorretos quando uma palavra está contida em outra. A correção para isso adiciona outros 13 caracteres:
Aqui está a versão limpa:
É possível raspar alguns caracteres à custa da correção teórica usando em
range(99)
vez derange(len(x))
(créditos ao tremor por pensar nisso).fonte
'LOREM', 'ORE', 'R'
produz incorretamente a saídaLOREMORER
.Python, 144 caracteres
S
pega um conjunto de palavrasA
que ainda precisam ser colocadas e uma sequências
contendo as palavras colocadas até o momento. Nós escolher uma palavra restantea
doA
e se sobrepõem-lo de0
delen(a)
caracteres com o fim des
.Leva apenas cerca de 0,15 segundos no exemplo fornecido.
fonte
['LOREM', 'ORE', 'R']
. Tomei a liberdade de consertar isso e aprimorar sua solução um pouco mais: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
(não é necessária uma segunda linha). Uso:S({'LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE'})
retorna'SEDOLOREMAGNAD'
.Haskell, 121
Menos dois se a função não precisar ser vinculada a um nome
fonte