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