Berechnen Sie minimale String-Segmentgrößen

8

Eine übliche Optimierung, um Platz in Binärdateien zu sparen, besteht darin, Zeichenfolgenliterale zusammenzuführen, wobei ein Literal das Suffix eines anderen ist. Zum Beispiel eine Binärdatei mit den Zeichenfolgenliteralen

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

enthält möglicherweise den folgenden String-Literal-Pool ( #der den \0-terminator darstellt):

foobar#foobarbaz#

mit den Symbolen a, b, c, und dmit den folgenden Werten in Bezug auf den Anfang des Zeichenfolge Pools:

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

In dieser Aufgabe müssen Sie die minimale Größe eines Zeichenfolgenpools für einen bestimmten Satz von Eingabezeichenfolgen berechnen.

Eingang

Die Eingabe besteht aus einer Reihe von bis zu 999 Zeichenfolgen mit jeweils bis zu 80 ASCII-Zeichen (ohne Zeilenumbruch) im Bereich von 32 bis einschließlich 127 und einem einzelnen Zeilenumbruchzeichen.

Ausgabe

Suchen Sie die kürzeste Zeichenfolge, sodass jede der Eingabezeichenfolgen (einschließlich der abschließenden Zeilenumbrüche) Teilzeichenfolgen dieser Zeichenfolge sind. Die Ausgabe muss die Länge dieser kürzesten Zeichenfolge sein. Geben Sie den String nicht aus, sondern nur seine Länge.

Wertung

Diese Herausforderung ist Code Golf, es gelten Standardlücken. Die Lösung mit der geringsten Länge in Oktetten gewinnt.

Beispiele

  1. Eingang:

    foobar
    bar
    barbaz
    foobarbaz
    baz
    

    kürzeste Zeichenfolge, #die Zeilenumbruch darstellt:

    foobar#foobarbaz#
    

    Länge: 17

  2. Eingang:

    foobar
    foobaz
    foobarbaz
    barbaz
    

    kürzeste Zeichenfolge, #die Zeilenumbruch darstellt:

    foobar#foobaz#foobarbaz#
    

    Länge: 24

FUZxxl
quelle
1
Und ein Testfall mit 80 Zeichen wäre gut. Gibt es auch einen Unterschied zwischen "Oktett" und "Byte"? Ansonsten bin ich mir nicht sicher, welchen Nutzen die Verwendung des obskureren Begriffs hat.
Martin Ender
1
@ MartinBüttner Auf einigen Maschinen hat ein Byte mehr oder weniger als 8 Bit (vgl. Knuths MIX). Oktett ist das Standardwort für eine 8-Bit-Menge. Byte bezieht sich auf die am wenigsten adressierbare Einheit der jeweiligen Maschine, an der Sie arbeiten. Das Limit von 80 Zeichen ist nur vorhanden, damit Benutzer mit festen Arrays arbeiten können. Daher kann ich nicht sagen, dass dies ungültig ist, da es bei sehr langen Eingaben unterbrochen wird.
FUZxxl
1
Sind alle Eingabezeichenfolgen paarweise unterschiedlich?
Alexey Burdin
@ AlexeyBurdin Nr.
FUZxxl

Antworten:

4

Pyth, 20 18 Bytes

hljb-{.zsmteM./d.z

Demonstration.

{ kann entfernt werden, wenn Duplikate nicht zulässig sind.

Erläuterung:

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

CJam, 22 Bytes

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

Probieren Sie es online aus.

Wie es funktioniert

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

Python 2, 132

Nur um ein Rennen zu starten:

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)

Es klappt:

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

Haskell, 101 85 Bytes

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

Eine Funktion ohne Namen. Anwendungsbeispiel:

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

So funktioniert es: Eingabezeichenfolge in Zeilenumbrüchen teilen. Entfernen Sie Duplikate aus der Wortliste l. Behalten Sie ein Wort xaus der verbleibenden Liste bei, wenn es nicht in der Liste aller Schwänze der Wörter von enthalten ist l. Verbinden Sie diese xmit Zeilenumbrüchen dazwischen (und am Ende!) Zu einer einzelnen Zeichenfolge und zählen Sie deren Länge.

Nimi
quelle