John Reiser explained on comp.compression:
per il dizionario: fare una istogramma di brevi stringhe, ordina per payoff (numero di occorrenze volte il numero di bit salvato quando compressi) e mettere le sottostringhe con il più alto profitto nel dizionario. Ad esempio, se k è la lunghezza della sottostringa più breve che può essere compressa (di solito 3 == k o 2 == k), quindi creare un istogramma di tutte le sottostringhe delle lunghezze k, 1 + k, 2 + k, e 3 + k. Naturalmente c'è una certa arte di porre quelle sottostringhe nel dizionario, sfruttando stringhe, si sovrappongono, brevi stringhe più vicino alla fascia alta-indirizzo, ecc
Il kernel Linux usa una tecnica simile per comprimere i nomi di simboli che vengono utilizzati per stampare i backtrace dello stack delle chiamate di subroutine. Vedi gli script di file/kallsyms.c. Per esempio, https://code.woboq.org/linux/linux/scripts/kallsyms.c.html
La zlib manual recommends per posizionare le occorrenze più comuni alla fine del dizionario.
Il dizionario deve essere composto da stringhe (sequenze di byte) che possono essere rilevate più avanti nei dati da comprimere, con le stringhe più comunemente utilizzate preferibilmente posizionate verso la fine del dizionario. L'utilizzo di un dizionario è molto utile quando i dati da comprimere sono brevi e possono essere previsti con una buona precisione; i dati possono quindi essere compressi meglio rispetto al dizionario vuoto predefinito.
Questo perché LZ77 ha un algoritmo a finestra scorrevole, quindi le sottostringhe successive saranno raggiungibili ulteriormente sul flusso di dati rispetto ai primi.
Mi piacerebbe giocare con la generazione del dizionario con un linguaggio di livello superiore con un buon supporto di stringhe. Un grezzo esempio JavaScript:
var str = "The dictionary should consist of strings (byte sequences) that"
+ " are likely to be encountered later in the data to be compressed,"
+ " with the most commonly used strings preferably put towards the "
+ "end of the dictionary. Using a dictionary is most useful when the"
+ " data to be compressed is short and can be predicted with good"
+ " accuracy; the data can then be compressed better than with the "
+ "default empty dictionary.";
// Extract words, remove punctuation (extra: replace(/\s/g, " "))
var words = str.replace(/[,\;.:\(\)]/g, "").split(" ").sort();
var wcnt = [], w = "", cnt = 0; // pairs, current word, current word count
for (var i = 0, cnt = 0, w = ""; i < words.length; i++) {
if (words[i] === w) {
cnt++; // another match
} else {
if (w !== "")
wcnt.push([cnt, w]); // Push a pair (count, word)
cnt = 1; // Start counting for this word
w = words[i]; // Start counting again
}
}
if (w !== "")
wcnt.push([cnt, w]); // Push last word
wcnt.sort(); // Greater matches at the end
for (var i in wcnt)
wcnt[i] = wcnt[i][1]; // Just take the words
var dict = wcnt.join("").slice(-70); // Join the words, take last 70 chars
Poi dict è una stringa di 70 caratteri con:
rdsusedusefulwhencanismostofstringscompresseddatatowithdictionarybethe
si può provare copia-incolla-run here (aggiungere: "stampare (dict)")
Queste sono solo parole intere, non sottostringhe. Esistono anche modi per sovrapporre sottostringhe comuni per risparmiare spazio sul dizionario.
l'ordinamento non funziona con intero, vedere http://stackoverflow.com/questions/1063007/sort-not-working-with-integers – Fabien
Esiste un modo per "esportare" il dizionario creato comprimendo un file in modo da applicarlo per i file successivi, cioè per "addestrare" automaticamente il dizionario? – rustyx
@RustyX, è possibile utilizzare [infgen] (https://github.com/madler/infgen) per vedere la struttura dei dati compressi e da ciò vedere quali valori letterali nei dati vengono referenziati più spesso. Con un dizionario personalizzato è possibile garantire che siano presenti sottosequenze di corrispondenza più lunghe e ottenere un rapporto di compressione migliore. –