SAPIENZA UNIVERSITA` DI ROMA APPUNTI ALGORITMI
Transcript
SAPIENZA UNIVERSITA` DI ROMA APPUNTI ALGORITMI
SAPIENZA UNIVERSITA’ DI ROMA APPUNTI ALGORITMI PER LA FATTORIZZAZIONE DI STRINGHE Sergio De Agostino 1 1. Introduzione Siano A e B alfabeti finiti e g : A∗ − > B ∗ una funzione. La funzione g e’ computabile on-line solo se esiste un algoritmo AL che per ogni stringa input S di A∗ calcola g(S) in modo tale che: AL legge S da sinistra a destra; quando AL legge l’ i-esimo carattere di S puo’ accedere solo all’ informazione fornita dal prefisso di lunghezza i di S (i caratteri gia’ letti). La funzione g potrebbe anche essere parziale (definita solo su un sottoinsieme di A∗ ). In tal caso, l’ algoritmo riconosce se l’ input e’ una stringa su cui la funzione non e’ definita e la rifiuta. Se la funzione e’ definita su tutte le stringhe si dice totale. Definito come sopra, AL e’ un algoritmo con memoria illimitata. AL e’ un algoritmo on-line con memoria finita se quando legge l’ i-esimo carattere di S puo’ accedere solo all’ informazione fornita dagli ultimi k caratteri letti (il suffisso di lunghezza k del prefisso di lunghezza i di S). Un algoritmo on-line si dice algoritmo in tempo reale se durante la sua esecuzione impiega un tempo costante su ogni carattere letto. Le macchine a stati finiti (come, ad esempio, la macchina di Mealy vista nel corso di Progettazione di Sistemi Digitali) sono algoritmi in tempo reale che avanzano sempre nella lettura della stringa senza accedere mai all’ informazione gia’ letta e sono il modello computazionale piu’ semplice di interesse pratico. Nella sua formulazione piu’ generale, una macchina a stati finiti M e’ una sestupla (A, B, Q, δ, q0 , F ) con alfabeto input A, alfabeto output B, insieme degli stati Q, funzione δ : QxA− > QxB ∗ , stato iniziale q0 e insieme degli stati finali F ⊆ Q. Come noto dal corso di Algebra, A∗ e’ un monoide con la concatenazione tra stringhe come operazione associativa e la stringa vuota λ come elemento identita’. L’ insieme A+ = A∗ −λ e’ un semigruppo rispetto a tale operazione. Ogni sottostringa di un stringa S di A∗ e’ un fattore di S e una qualsiasi concatenazione di stringhe uguale a S e’ una fattorizzazione di S. 2 Un insieme D = A ∪ {fi : fi ∈ A+ , 1 ≤ i ≤ k} si dice dizionario di fattori. Ogni stringa di A∗ e’ fattorizzata rispetto a D se viene rappresentata come concatenazione di elementi di D. Ogni stringa di A∗ e’ fattorizzabile rispetto a D dato che i caratteri di A sono elementi di D. La fattorizzazione di una stringa S in A∗ si puo’ rappresentare con una sequenza binaria della stessa lunghezza di S dove un bit e’ uguale a 1 se e solo se la sua posizione e’ uguale a quella del primo carattere di un fattore. Una procedura di fattorizzazione rispetto a un dizionario e’ allora rappresentata da una funzione totale g : A∗ − > {0, 1}∗ . 2. Fattorizzazioni rispetto a un Dizionario Dato un alfabeto finito A e un corrispondente dizionario D, una fattorizzazione di una stringa S in A∗ rispetto a D e’ minima se il numero di fattori e’ minimo. La fattorizzazione minima di una stringa rispetto a un dizionario arbitrario non e’ calcolabile on-line. In modo off-line, si puo’ utilizzare la programmazione dinamica o una riduzione al problema del calcolo del cammino minimo tra due nodi di un grafo orientato aciclico non pesato (lasciati come esercizi per lo studente). Descriviano, ora, una procedura di fattorizzazione greedy on-line. La procedura legge la stringa da sinistra a destra e calcola a ogni passo il fattore piu’ lungo del dizionario nella posizione corrente. In generale, la procedura non produce una fattorizzazione minima come dimostra il seguente esempio (a concatenato n volte e’ denotato con an ): Esempio: baban ; dizionario: a, b, ba, bab, ban fattorizzazione minima: ba,ban ; fattorizzazione greedy on-line: bab, a, a, ..., a, ...a Il dizionario viene di solito rappresentato da un albero radicato con archi etichettati dai caratteri dell’ alfabeto e i nodi etichettati da 0 o 1. La radice dell’ albero rappresenta la stringa vuota e ogni fattore e’ rappresentato da un 3 cammino dalla radice a un nodo etichettato con 1 (la sequenza dei caratteri del fattore corrisponde alle sequenza delle etichette degli archi del cammino). I nodi etichettati con 0 corrispondono a prefissi di fattori del dizionario che non sono elementi del dizionario stesso. Come realizzare la procedura di fattorizzazione greedy on-line in tempo reale utilizzando tale struttura dati per il dizionario e’ un facile esercizio (essendo il dizionario definito a priori, si puo’ assumere che la lunghezza dei fattori sia costante). Piu’ complicato e’ realizzare la fattorizzazione greedy on-line con una macchina a stati finiti. Gli archi dell’ albero rappresentante un dizionario D sono orientati da padre a figlio. Costruiamo la macchina a stati finiti partendo dall’ albero, il cui insieme dei nodi rappresenta l’ insieme degli stati. Come detto nell’ introduzione, la funzione da calcolare e’ totale (ovviamente, l’ alfabeto input e’ A e l’ alfabeto output e’ quello binario). Quindi, tutti gli stati sono finali. La radice e’ lo stato iniziale. Bisogna solo completare la funzione δ aggiungendo gli archi mancanti. Agli archi gia’ presenti e’ associato come output la stringa vuota. Per ogni nodo, gli archi uscenti rappresentano un sottoinsieme dell’ alfabeto input. Sia f la stringa corrispondente al nodo v dell’ albero e a un carattere dell’ alfabeto a cui non corrisponde un arco uscente da v. Sia f a = f1 · · · fk la fattorizzazione greedy on-line di f a e i il piu’ piccolo indice tale che fi+1 · · · fk e’ rappresentato da un nodo w dell’ albero. Allora, aggiungiamo all’ albero un arco orientato da v a w con etichetta a trasformandolo in un grafo orientato aciclico. L’ output associato all’ arco e’ la stringa binaria che rappresenta la sequenza di fattori f1 · · · fi . Aggiungendo un arco siffatto per tutti i nodi e tutti i caratteri a cui non corrisponde un arco uscente la funzione δ e’ interamente definita. Un dizionario D e’ prefisso (suffisso) se tutti i prefissi (suffissi) di un elemento di D sono elementi di D. E’ facile dimostrare che la fattorizzazione greedy on-line e’ sempre minima se il dizionario e’ suffisso (esercizio per lo studente). Non lo e’ nel caso di un dizionario prefisso: Esempio: baban ; dizionario: a, b, ba, bab, bai per 1 ≤ i ≤ n fattorizzazione minima: ba,ban ; fattorizzazione greedy on-line: bab, a, a, ..., a, ...a 4 La fattorizzazione minima rispetto a un dizionario prefisso e’ comunque calcolabile dalla seguente procedura on-line (x1 · · · xn e’ la stringa input): j:=0; i:=0; ripeti fino a fine stringa per k = j + 1 a i + 1 sia h(k): xk ...xh(k) e’ il piu’ lungo fattore in posizione k sia k ′ tale che h(k ′ ) e’ massimo xj ...xk′ −1 e’ selezionato come fattore j := k ′ ; i := h(k ′ ) La procedura e’ anche detta semi-greedy poiche’ dopo aver calcolato il fattore greedy corrente, correggiamo la scelta selezionando il prefisso a cui succede il fattore greedy che finisce piu’ a destra. Tale procedura on-line non e’ eseguibile da una macchina a stati finiti ma ha accesso limitato agli ultimi ℓ caratteri letti dove ℓ e’ la lunghezza massima di un fattore del dizionario. Come esercizio per lo studente, dimostrare che la procedura semi-greedy calcola la fattorizzazione minima se il dizionario e’ prefisso. Dare. anche, la complessita’ se il dizionario e’ rappresentato da un albero. 5