Calcular tamaños mínimos de segmento de cadena

8

Una optimización común para ahorrar espacio en binarios es fusionar literales de cadena donde un literal es el sufijo de otro. Por ejemplo, un binario con los literales de cadena

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

podría contener el siguiente grupo literal de cadenas (que #representa el \0-terminador):

foobar#foobarbaz#

con los símbolos a, b, c, y dque tiene los siguientes valores relativos al principio de la cadena de la piscina:

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

En esta tarea, debe calcular el tamaño mínimo de un grupo de cadenas para un conjunto determinado de cadenas de entrada.

Entrada

La entrada es una serie de hasta 999 cadenas, cada una de las cuales comprende hasta 80 caracteres ASCII (sin incluir la nueva línea) en el rango de 32 a 127 inclusive y luego un solo carácter de nueva línea.

Salida

Encuentre la cadena más corta de manera que cada una de las cadenas de entrada (incluidas las nuevas líneas de terminación) sean subcadenas de esa cadena. La salida será la longitud de esa cadena más corta. No envíe la cadena, solo su longitud.

Puntuación

Este desafío es el código de golf, se aplican las lagunas estándar. La solución con la menor longitud en octetos gana.

Ejemplos

  1. Entrada:

    foobar
    bar
    barbaz
    foobarbaz
    baz
    

    cadena más corta, que #representa nueva línea:

    foobar#foobarbaz#
    

    longitud: 17

  2. Entrada:

    foobar
    foobaz
    foobarbaz
    barbaz
    

    cadena más corta, que #representa nueva línea:

    foobar#foobaz#foobarbaz#
    

    longitud: 24

FUZxxl
fuente
1
Y el caso de prueba de 80 caracteres sería bueno. Además, ¿hay alguna diferencia entre "octeto" y "byte"? De lo contrario, no estoy seguro de cuál es el beneficio de usar el término oscuro.
Martin Ender
1
@ MartinBüttner En algunas máquinas, un byte tiene más o menos de 8 bits (cf. Knuth's MIX). Octeto es la palabra estándar para referirse a una cantidad de 8 bits, byte se refiere a la unidad menos direccionable de la máquina particular en la que está trabajando. El límite de 80 caracteres está ahí para que las personas puedan trabajar con arreglos fijos y no puedo decir "esto no es válido porque se rompe con una entrada muy larga".
FUZxxl
1
¿Todas las cadenas de entrada son distintas por pares?
Alexey Burdin
@AlexeyBurdin No.
FUZxxl

Respuestas:

4

Pyth, 20 18 bytes

hljb-{.zsmteM./d.z

Demostración.

{ puede eliminarse si no se permiten duplicados.

Explicación:

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
fuente
3

CJam, 22 bytes

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

Pruébalo en línea.

Cómo 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
fuente
1

pitón 2, 132

Solo para comenzar una carrera:

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
fuente
1

Haskell, 101 85 bytes

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

Una función sin nombre. Ejemplo de uso:

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

Cómo funciona: dividir la cadena de entrada en las nuevas líneas. Eliminar duplicados de la lista de palabras l. Mantenga una palabra xde la lista restante si no está en la lista de todas las colas de las palabras de l. Únete a aquellos xcon nuevas líneas intermedias (¡y al final!) En una sola cadena y cuenta su longitud.

nimi
fuente