Comprensione della compressione / codifica in tempo lineare


8

Sto leggendo l'articolo NJ Larsson, A. Moffat: Compressione basata su dizionario offline , che descrive un algoritmo di compressione che, se lo capisco correttamente, è abbastanza simile alla codifica delle coppie di byte .

Dato una stringa S di lunghezza n, Sto cercando di capire come comprimerlo in modo lineare, O(n), tempo con questo metodo di compressione. Com'è fatto esattamente? Ho letto il documento, ma ancora non capisco come raggiungono il tempo lineare, quindi forse lo capirei spiegato in un modo diverso.

La mia prima confusione sorge nel primo passo dell'algoritmo, in cui troviamo la coppia più comune, ad esempio nella abcababcabccoppia più comune absarebbe sostituita da un nuovo simbolo, diciamo XcXXcXc. Non capisco come possiamo trovare la coppia più comune abbastanza rapidamente. Il mio approccio ingenuo sarebbe quello di guardare prima la prima coppia abe poi contare il numero di occorrenze, quindi guardare la coppia successiva bce contare il numero di occorrenze, ecc. Tuttavia questo già darebbeO(n2)solo per trovare la coppia più comune una volta .

Successivamente, anche se ho capito come trovare la coppia più comune in O(n)tempo. Il mio prossimo problema è che, non dobbiamo trovare la coppia più comune fino aO(n)volte? E quindi questo darebbe un tempo totale diO(n2)?


Dovresti porre una domanda più specifica. Ribadire un documento con parole diverse sembra estendersi a questo sito. In quale punto degli articoli ti perdono gli autori?
adrianN,

@adrianN Ho scritto un po 'di più su ciò che in particolare sono confuso.
Eff

Il documento ha ipotizzato che utilizzerà la tabella hash e lo ha contato come O(n), che in questo caso potrebbe essere wlog sostituito dall'albero del suffisso O(n). Ho appena sfogliato il testo, la tua domanda è ancora molto impegnativa, ma non vedo davvero perché dovresti spendereO(n2)solo per un oggetto.
Male

@Evil Quindi stai dicendo che si potrebbe costruire un albero di suffissi S in Θ(n) tempo (A proposito, non riesco ancora a capire quando è possibile costruire un albero di suffissi in tempo lineare e quando ci vuole O(nlogn)). Quindi troviamo la sottostringa più frequente nell'albero dei suffissi inΘ(n)tempo. Corretta?
Eff

Me? No. Ma Ukkonen ha detto qualche parola al riguardo.O(n) per alfabeto di dimensioni costanti e O(nlogn)in generale. Quindi possiamo ordinare in base alle frequenzeO(nlogn)o persino sfruttare piccoli numeri naturali per contare l'ordinamento. Non sono sicuro che qualcosa sia 1 ~ nΘ(n), scusa nessuna risposta per quella parte.
Male

Risposte:


1

Ho controllato il codice, ho riletto il foglio e sembra che l'algoritmo non funzioni O(n)nel modo in cui hai descritto.
Le chiamate ricorsive di trovare coppie funzionanoO(nlogn)diviso per costante se si desidera imballarlo fino alla fine. In effetti la struttura sottostante mantiene i puntatori alla prima occorrenza della coppia, suddivide la coda delle coppie per occorrenze per renderla efficiente, ma comunque loglineare. D'altra parte analizzando il codice scritto da Ph.D. studente dell'autore ho scoperto diversi trucchi: la lunghezza delle coppie (il nome originale) è indicata come parametro (il valore predefinito è 2) e la ricorrenza è limitata dal parametro, che può scartare ulteriori chiamate (il valore predefinito è di circa 5 livelli), con capacità di fare solo un passaggio o spingere fino alla fine. Viene eseguito il codice predefinitoO(n), ma non produrrà una compressione ottimale. C'è anche un interruttore per preferire memoria, tempo o essere neutro.

L'articolo e il codice mostrano l'uso dell'hash-table, che viene eseguito solo nel tempo costante previsto, ma la funzione fornita funziona molto bene con i caratteri. Inoltre, il codice limita la lunghezza dell'input mediante costante hardcoded.

Cambiare la tabella hash in suffisso dell'albero e riscrivere la parte della ricorrenza in coppie parziali di contabilità potrebbe produrre risultati migliori - Non sono sicuro che sia possibile farlo O(n), questa sarebbe probabilmente una domanda diversa.

C'è anche un trucco usato per evitare che lo spazio vuoto si attraversi: l'inizio del blocco vuoto punta al primo carattere non vuoto, ma questo accelera solo l'attraversamento, sempre con il tempo loglineare. La parte responsabile di questo comportamento sta sostituendo le coppie con il nuovo carattere ogni iterazione - mantenere solo le regole di riscrittura e operare su di esse sarebbe più veloce, ma comunque l'accesso per verificare se fossero state introdotte nuove coppie richiederebbe di controllare le regole di riscrittura con quelle nuove - nel caso in cui costruiamo un albero binario completo con coppie alle foglie in modo tale che dopo aver sostituito le coppie con un nuovo personaggio e averlo concordato con il genitore abbiamo ottenuto nuove coppie alle foglie fino alla radice - ci sonon chat quindi n2 coppie, quindi n4, n8, n16... Vedi lo schema, ci sono 2n coppie, ma in base alla descrizione dell'algoritmo ciò si verifica O(nlogn+n) prendendo tempo solo traversali di input.

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.