Un algoritmo di compressione efficiente per stringhe di testo brevi [chiuso]


126

Sto cercando un algoritmo per comprimere stringhe di testo di piccole dimensioni: 50-1000 byte (ovvero URL). Quale algoritmo funziona meglio per questo?


1
Dove vuoi usare queste stringhe compresse?
Gumbo,

1
Sta andando verso tinyurlso qualcosa a che fare con lo spazio di archiviazione?
nik,

6
Sono interessato a un algoritmo per la compressione degli URL, il miglior rapporto di compressione è più importante dei costi di gestione. Non interessato a servizi online come tinyurls o tr.im. Sto cercando un algoritmo non un servizio. Non pensare che qualsiasi altra informazione possa essere utile ...
Vasily Korolev,

3
@Gumbo: "Algoritmi di compressione del testo per stringhe brevi" sono sufficienti per trovare gli algos, perché sei così interessato a sapere a cosa servono? Sono sicuro che l'OP sarà in grado di trovare quello che fa quello che vuole.
Dervin Thunk,

7
@Vasily, un piccolo suggerimento: ogni volta che fai una domanda su SO sotto forma di "Qual è la migliore XYZ?", La tua domanda è quasi destinata a ricevere voti per la chiusura perché chiedere il migliore potrebbe portare a prodotti non necessari confronti, o nel peggiore dei casi, anche guerre di fiamma. (Di solito ci vuole solo una piccola modifica per evitarlo: se ponessi la stessa domanda del tipo "Per favore, suggerisci una XYZ.", Non otterrai tanti voti di chiusura, anche se sostanzialmente è la stessa domanda!)
stakx - non contribuisce più il

Risposte:


62

Dai un'occhiata a Smaz :

Smaz è una semplice libreria di compressione adatta per comprimere stringhe molto brevi.


17
Vedi github.com/antirez/smaz/blob/master/smaz.c - questa è una variante della codifica, non della compressione in sé (almeno non del tutto). Usa un dizionario statico di parole e lettere.
Roy Tinker,

7
Nota: questo è il progetto di Antirez. È uno dei principali autori di Redis e ha una solida reputazione nel rilasciare codice di produzione di alta qualità.
Homer6

7
L'algoritmo smaz è ottimizzato per i testi in inglese, quindi non funziona bene con stringhe casuali. Ecco alcuni esempi ( string:orig_size:compr_size:space_savings): This is the very end of it.:27:13:52%, Lorem ipsum dolor sit amet:26:19:27%, Llanfairpwllgwyngyll:20:17:15%, aaaaaaaaaaaaa:13:13:0%, 2BTWm6WcK9AqTU:14:20:-43%,XXX:3:5:-67%
mykhal

4
Dai anche un'occhiata a una compressione più bassa ma un algoritmo veloce shoco ed-von-schleck.github.io/shoco
Dickey Singh

Aggiungi la mia libreria Unishox all'elenco github.com/siara-cc/unishox . Funziona meglio di Smaz e Shoco e supporta la compressione delle stringhe UTF-8.
arun

28

Huffman ha un costo statico, il tavolo Huffman, quindi non sono d'accordo che sia una buona scelta.

Esistono versioni adattative che eliminano ciò, ma il tasso di compressione potrebbe risentirne. In realtà, la domanda che dovresti porre è "quale algoritmo per comprimere le stringhe di testo con queste caratteristiche". Ad esempio, se sono previste lunghe ripetizioni, la semplice codifica Run-Lengh potrebbe essere sufficiente. Se puoi garantire che saranno presenti solo parole inglesi, spazi, punteggiatura e cifre occasionali, allora Huffman con una tabella Huffman predefinita potrebbe produrre buoni risultati.

Generalmente, gli algoritmi della famiglia Lempel-Ziv hanno una compressione e prestazioni molto buone e abbondano le loro librerie. Vorrei andare con quello.

Con l'informazione che ciò che viene compresso sono URL, allora suggerirei che, prima di comprimerlo (con qualunque algoritmo sia facilmente disponibile), li CODIFICI. Gli URL seguono schemi ben definiti e alcune parti sono altamente prevedibili. Facendo uso di questa conoscenza, è possibile codificare gli URL in qualcosa di più piccolo per cominciare, e le idee alla base della codifica Huffman possono aiutarti qui.

Ad esempio, traducendo l'URL in un flusso di bit, è possibile sostituire "http" con il bit 1 e qualsiasi altra cosa con il bit "0" seguito dall'attuale procotol (o utilizzare una tabella per ottenere altri protocolli comuni, come https, ftp, file). ": //" può essere eliminato del tutto, purché sia ​​possibile contrassegnare la fine del protocollo. Ecc. Leggi il formato URL e pensa a come possono essere codificati per occupare meno spazio.


4
Non se la tabella huffman è la stessa per tutti i file, il che avrebbe senso se i file fossero tutti simili tra loro.
Finnw,

1
Se hai molti file simili simili, stai sbagliando tutto. Prima concatenali tutti (come fa tar), quindi comprimili. Otterrai una compressione migliore e il problema cessa di essere "50-1000 byte".
Daniel C. Sobral,

8
@Daniel: dipende se si desidera un accesso casuale ai dati compressi. Comprimere tutto insieme impedisce questo con la maggior parte dei sistemi di compressione.
Steve Jessop,

22

Non ho un codice a portata di mano, ma mi è sempre piaciuto l'approccio alla costruzione di una tabella di ricerca 2D di dimensioni 256 * 256 caratteri ( RFC 1978 , protocollo di compressione Predictor PPP ). Per comprimere una stringa esegui il ciclo su ciascun carattere e utilizza la tabella di ricerca per ottenere il carattere successivo "previsto" utilizzando il carattere corrente e precedente come indici nella tabella. Se c'è una corrispondenza, scrivi un singolo 1 bit, altrimenti scrivi uno 0, il carattere e aggiorna la tabella di ricerca con il carattere corrente. Questo approccio mantiene sostanzialmente una tabella di ricerca dinamica (e grezza) del prossimo personaggio più probabile nel flusso di dati.

Puoi iniziare con una tabella di ricerca azzerata, ma ovviamente funziona meglio su stringhe molto brevi se viene inizializzato con il carattere più probabile per ciascuna coppia di caratteri, ad esempio per la lingua inglese. Finché la tabella di ricerca iniziale è la stessa per la compressione e la decompressione non è necessario emetterla nei dati compressi.

Questo algoritmo non offre un brillante rapporto di compressione, ma è incredibilmente semplice con risorse di memoria e CPU e può anche lavorare su un flusso continuo di dati: il decompressore mantiene la propria copia della tabella di ricerca mentre si decomprime, quindi la tabella di ricerca si adatta al tipo di dati compressi.


Ma come si comporterebbe il predittore con la normale frase inglese? L'esempio dato ha una ridondanza molto forte e il guadagno è minimo.
Danubian Sailor,

Una tabella di ricerca 256 * 256 non suona "incredibilmente frugale con la memoria" ...!
MikeW,

@MikeW Beh, sono 65 kilobyte.
redcalx,

@redcalx Se fosse stato di 65 byte avrei potuto essere d'accordo!
MikeW,

11

Qualsiasi algoritmo / libreria che supporti un dizionario predefinito, ad esempio zlib .

In questo modo è possibile adescare il compressore con lo stesso tipo di testo che è probabile che appaia nell'input. Se i file sono simili in qualche modo (ad es. Tutti gli URL, tutti i programmi C, tutti i post StackOverflow, tutti i disegni di arte ASCII), alcune sottostringhe appariranno nella maggior parte o in tutti i file di input.

Ogni algoritmo di compressione consente di risparmiare spazio se la stessa sottostringa viene ripetuta più volte in un file di input (ad es. "The" in inglese o "int" in codice C.)

Ma nel caso di URL determinate stringhe (ad es. " Http: // www .", ".Com", ".html", ".aspx" appariranno in genere una volta in ciascun file di input. Quindi è necessario condividerle tra i file in qualche modo piuttosto che avere un'occorrenza compressa per file. Posizionandoli in un dizionario preimpostato si otterrà questo.


2
Suggerimenti sull'uso del dizionario personalizzato: stackoverflow.com/questions/2011653
Trenton,


4

Se stai parlando di comprimere effettivamente il testo non solo di accorciare, quindi Deflate / gzip (wrapper attorno a gzip), zip funziona bene per file e testo più piccoli. Altri algoritmi sono altamente efficienti per file più grandi come bzip2 ecc.

Wikipedia ha un elenco di tempi di compressione. (cerca il confronto di efficienza)

Name       | Text         | Binaries      | Raw images
-----------+--------------+---------------+-------------
7-zip      | 19% in 18.8s | 27% in  59.6s | 50% in 36.4s
bzip2      | 20% in  4.7s | 37% in  32.8s | 51% in 20.0s
rar (2.01) | 23% in 30.0s | 36% in 275.4s | 58% in 52.7s
advzip     | 24% in 21.1s | 37% in  70.6s | 57& in 41.6s
gzip       | 25% in  4.2s | 39% in  23.1s | 60% in  5.4s
zip        | 25% in  4.3s | 39% in  23.3s | 60% in  5.7s

6
Vuole comprimere il testo e non i file.
Gumbo,

3
Puoi comprimere testo e binari con questi algoritmi. In effetti usiamo deflate all'interno di un sistema cms che gira su Python.
Ryan Christensen,

Un esempio in C # che utilizza gzip per le stringhe è qui: csharphelp.com/archives4/archive689.html
Ryan Christensen,

modulo zlib in python per la compressione di stringhe: python.org/doc/2.5.2/lib/module-zlib.html
Ryan Christensen,

3
gzip (e zlib) usa deflate e aggiunge il wrapper / overhead di framing .. direct deflate / LZ77 (l'overhead del dizionario e l'efficienza dipendono ancora dall'implementazione di tali e impostazioni) possono ridurre l'overhead di pareggio. Questo è per stringhe "brevi" in decine o centinaia di caratteri, ovviamente (dovrebbe ancora avere un po 'per indicare "era compresso"? Per evitare di ingrandire i dati). Le spese generali maggiori non contano ... all'aumentare del testo. I numeri pubblicati qui sembrano essere per file di testo di grandi dimensioni (molti secondi per essere eseguiti!), Mentre OP richiede 50-1000 carte - molto piccole in confronto.
user2864740

2

Potresti dare un'occhiata allo schema di compressione standard per Unicode .

SQL Server 2008 R2 lo utilizza internamente e può ottenere una compressione fino al 50%.


SCSU "comprime" Unicode non inglese nelle codifiche UTF-16 / MB. Se Unicode basato su inglese / plain-old-ASCII, UTF-8 'comprime' anche il 50% di UTF-16 ..
user2864740
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.