2008-09-29 14 views
2

Problem gibt:das beste Kompression

eine Liste von Strings Gegeben, finden den Teil die, wenn sie von Anfang an von allen Saiten abgezogen, wo sie paßt und durch einen Escape-Byte ersetzt, gibt die kürzeste Gesamtlänge

Beispiel:

"foo", "fool", "bar"

Das Ergebnis ist: "foo", wie die Basiszeichenfolge mit den Zeichenfolgen "\0", "\0l", "bar" und einer Gesamtlänge von 9 Bytes. "\0" ist das Escape-Byte. Die Summe der Länge der ursprünglichen Strings ist 10, also haben wir in diesem Fall nur ein Byte gespeichert.

Ein naiver Algorithmus würde wie folgt aussehen:

for string in list 
    for i = 1, i < length of string 
     calculate total length based on prefix of string[0..i] 
     if better than last best, save it 
return the best prefix 

, die uns die Antwort geben wird, aber es ist so etwas wie O ((n * m)^2), die zu teuer ist.

Antwort

6

Verwenden Sie einen Wald von Präfix Bäume (Trie) ...

f_2 b_1 
/  | 
o_2  a_1 
|  | 
o_2  r_1 
| 
l_1 

dann können wir das beste Ergebnis und garantieren, es finden, die von (depth * frequency) maximiert, die mit Ihrem Escape-Zeichen ersetzt werden. Sie können die Suche optimieren, indem Sie zuerst eine Verzweigung und eine gebundene Tiefe nach dem Maximum suchen.

Auf die Komplexität: O (C), wie in Kommentar erwähnt, für den Aufbau und für die Suche nach dem optimalen, es kommt darauf an. Wenn Sie die erste Elementhäufigkeit bestellen (O (A) - wobei A die Größe des Sprachenalphabets ist), können Sie mehr Zweige ausschneiden und haben eine gute Chance, eine sublineare Zeit zu erhalten.

Ich denke, das ist klar, ich werde es nicht aufschreiben - was ist das eine Hausaufgabe? ;)

+0

Hört sich gut an, obwohl ich denke, dass Sie wollen ((Tiefe - 1) * Frequenz), vorausgesetzt, die Größe der Ersetzung ist gleich der eines Zeichens (obwohl die Frage ein Byte sagt). Sollte in O (c) laufen, wobei c die Gesamtzahl der Zeichen ist. –

+0

Der erste Teil baut im Grunde genommen einen Trie aus einer Liste von Strings. – Tyler

+0

Haha, nein, es ist keine Hausaufgabe. Dafür bin ich viel zu alt. =) Ich habe eigentlich eine ziemlich gute, funktionierende Implementierung, aber es ist nicht garantiert, ein optimales Ergebnis zu liefern.Nette Idee mit einem Baum. –

1

Ich würde versuchen, indem Sie die Liste sortieren. Dann gehen Sie einfach von String zu String und vergleichen das erste Zeichen mit dem ersten Zeichen des nächsten Strings. Sobald Sie eine Übereinstimmung haben, würden Sie sich das nächste Zeichen anschauen. Sie müssen einen Weg finden, um das beste Ergebnis bisher zu verfolgen.

+0

Mit diesem Ansatz können Sie garantieren, dass Sie eine optimale Lösung haben werden? Wenn Sie immer das Zeichen auswählen, das Ihnen die meisten Zeichenfolgen mit demselben Präfix gibt, erhalten Sie das längste gemeinsame Präfix, und das ist möglicherweise nicht die beste Komprimierung. –

+0

Das würde sich auf den Teil über "Sie müssten einen Weg, um das beste Ergebnis bis jetzt verfolgen." – EBGreen

1

Nun, erster Schritt wäre, die Liste zu sortieren. Dann einen Durchlauf durch die Liste, wobei jedes Element mit dem vorherigen verglichen wird, wobei die längsten 2-Zeichen-, 3-Zeichen-, 4-Zeichen-usw.-Läufe verfolgt werden. Dann ist die Zahl der 20 3-stelligen Präfixe besser als die 15 4-stelligen Präfixe.