Calcular tamanhos mínimos de segmento de string

8

Uma otimização comum para economizar espaço nos binários é mesclar literais de cadeia de caracteres em que um literal é o sufixo de outro. Por exemplo, um binário com a string literal

a: foobar
b: bar
c: barbaz
d: foobarbaz
e: baz

pode conter o seguinte conjunto literal de cadeias ( #representando o \0-terminator):

foobar#foobarbaz#

com os símbolos a, b, ce dter os seguintes valores relativos ao início da piscina string:

a:  0
b:  3
c: 10
d:  7
e: 13

Nesta tarefa, você deve calcular o tamanho mínimo de um conjunto de cadeias para um determinado conjunto de cadeias de entrada.

Entrada

A entrada é uma série de até 999 strings, cada uma compreendendo até 80 caracteres ASCII (sem incluir a nova linha) no intervalo de 32 a 127 inclusive e, em seguida, um único caractere de nova linha.

Resultado

Encontre a cadeia mais curta, de modo que cada uma das cadeias de entrada (incluindo as novas linhas finais) sejam substrings dessa cadeia. A saída deve ser o comprimento dessa corda mais curta. Não produza a string, apenas seu comprimento.

Pontuação

Esse desafio é o código de golfe, são aplicadas brechas padrão. A solução com o menor comprimento em octetos vence.

Exemplos

  1. Entrada:

    foobar
    bar
    barbaz
    foobarbaz
    baz
    

    sequência mais curta, #representando nova linha:

    foobar#foobarbaz#
    

    comprimento: 17

  2. Entrada:

    foobar
    foobaz
    foobarbaz
    barbaz
    

    sequência mais curta, #representando nova linha:

    foobar#foobaz#foobarbaz#
    

    comprimento: 24

FUZxxl
fonte
1
E um caso de teste de 80 caracteres seria bom. Além disso, existe alguma diferença entre "octeto" e "byte"? Caso contrário, não tenho certeza de qual é o benefício de usar o termo obscurecedor.
Martin Ender
1
@ MartinBüttner Em algumas máquinas, um byte tem mais ou menos de 8 bits (consulte o MIX de Knuth). Octeto é a palavra padrão para se referir a uma quantidade de 8 bits, byte refere-se à unidade menos endereçável da máquina em que você está trabalhando. O limite de 80 caracteres existe apenas para que as pessoas possam trabalhar com matrizes fixas e, portanto, não posso dizer "isso é inválido porque quebra com entradas muito longas".
FUZxxl
1
Todas as seqüências de entrada são pareadas?
Alexey Burdin
@AlexeyBurdin No.
FUZxxl

Respostas:

4

Pitão, 20 18 bytes

hljb-{.zsmteM./d.z

Demonstração.

{ pode ser removido se duplicatas não forem permitidas.

Explicação:

hljb-{.zsmteM./d.z
                .z     The input, as a list of strings.
         m             Map each strings to
             ./d       all possible partitions of the string into separate strings.
           eM          take the last element of each, giving all suffixes.
          t            Remove the first suffix, giving all suffixes other than
                       the string itself.
        s              Sum, combining the list of lists into a single list.
    -{.z               From the set of input strings, remove all suffixes.
                       This is the list of strings in the minimal segment.
  jb                   Join the strings together on newlines.
 l                     Take the length of the resulting string.
h                      Add one and print.
isaacg
fonte
3

CJam, 22 bytes

qN%_&Nf+:G{Gs\/,3<},s,

Experimente online.

Como funciona

qN%   e# Split the input from STDIN at linefeeds, discarding the last, empty chunk.
_&    e# Intersect the array with itself to remove duplicates.
Nf+   e# Append a linefeed to each chunk.
:G    e# Save the result in G.
{     e# Filter; for each chunk in G:
  Gs  e#   Flatten the array of strings G.
  \/  e#   Split at occurrences of G.
  ,3< e#   Compare the resulting number of chunks with 3.
},    e#   Keep the chunk iff the comparision pushed 1 (true).
s,    e# Flatten the resulting array of strings and push the result's length.
Dennis
fonte
1

python 2, 132

Apenas para começar uma corrida:

def f(s):
    l=set(s.split('\n'))
    for x in l:
        for y in l:
            if x!=y and x.endswith(y):l.remove(y)
    return sum(len(x)+1 for x in l)

Funciona:

>>> f(r'''foobar
foobaz
foobarbaz
barbaz''')
24
>>> f(r'''foobar
bar
barbaz
foobarbaz
baz
''')
17
Alexey Burdin
fonte
1

Haskell, 101 85 bytes

import Data.List
length.unlines.(\l->[x|x<-nub l,x`notElem`((tails.tail)=<<l)]).lines

Uma função sem nome. Exemplo de uso:

*Main>  length.unlines.(\l->[x|x<-nub l,x`notElem`((tails.tail)=<<l)]).lines $ "foobar\nbar\nfoobaz"
14

Como funciona: divida a string de entrada nas novas linhas. Remova duplicatas da lista de palavras l. Mantenha uma palavra xda lista restante, se não estiver na lista de todas as caudas das palavras de l. Junte aqueles xcom novas linhas no meio (e no final!) A uma única sequência e conte o comprimento.

nimi
fonte