Prof.ssa Rossella Petreschi Lezione del 7 /01/ 2013 del Corso di Algoritmi e Strutture Dati Riferimenti: Capitolo 32 del testo Cormen,Leiserson,Rivest, Stein “Introduzione agli algoritmi” Edizioni: Jackson libri Corrispondenza fra stringhe Lezione n°23
Stringhe e Spostamenti Siano dati un testo T[1,…,n] e un pattern P [1,…,m] di caratteri presi da un alfabeto finito ∑ (T e P sono anche detti stringhe di caratteri) Problema: trovare tutte le occorrenze di P all’interno di T Diciamo che P appare con spostamento valido s in T se T[s+1,…,s+m]= P[1,…,m] Problema(seconda formulazione): trovare tutti gli spostamenti validi con cui un dato pattern P appare in un dato testo T. Definizioni: ∑ * : l’insieme di tutte le stringhe di lunghezza finita formate usando caratteri dell’alfabeto ∑ (si considerano solo stringhe di lunghezza finita) stringa vuota di lunghezza 0 appartenente a ∑ * xy : concatenazione di due stringhe x e y,ovvero creazione di una stringa di lunghezza x + y dove i caratteri di y seguono i caratteri di x.
Prefissi e Suffissi Una stringa w è un prefisso (suffisso) di una stringa x,w pre x (w suf x), se x=wy (x=yw), per qualche stringa y in ∑ * ( w ≤ x ) Vale: è sia prefisso che suffissso di ogni stringa; sia pre che suf sono relazioni transitive; w suf x sess wa suf xa, per qualunque carattere a (lo stesso per pre) Lemma: siano x,y e z stringhe tali che x suf z e y suf z, allora 1.x suf y, se x < y 2.y suf x, se y < x 3.y = x, se y = x Problema(terza formulazione): trovare tutti gli spostamenti s, 0≤s≤n-m, tali che P sia suffisso di T s+m P k (T k ) prefisso di k caratteri del pattern (testo) P(T)
Algoritmo Naif L’algoritmo naif trova tutti gli spostamenti validi controllando l’uguaglianza fra P [1,…,m] e T[s+1,…,s+m] per ognuno degli n-m+1 possibili valori di s for s = 0 to n-m do if P [1,…,m] = T[s+1,…,s+m] then stampa s Tempo computazionale: ((n-m+1)m) Si noti che: il tempo di pre-elaborazione è nullo; il tempo ((n-m+1)m) è stretto, ovvero può essere effettivamente raggiunto (p.e.si pensi a T=a n e P = a m ); il tempo ((n-m+1)m) è O(n 2 ), quando m è dell’ordine di n/2.
Nozioni di Teoria dei Numeri Regola di Horner per la valutazione di un polinomio A(x)=∑ a j x j (j= 0,…,n-1): A(x 0 )= a 0 +x 0 (a 1 +x 0 (a 2 +…+x 0 (a n-2 +x 0 (a n-1 )…) Es: 1251 = ∑ a j x j (j= 0,…,3) = a 0 +10(a 1 +10(a 2 +10a 3 )) = 1+10(5+10(2+10x1)) = = (5+10x12) = 1+10x125 = 1251 Classe di congruenza modulo n : [a] n = {a+kn: Z ∍ k} Es. [3] 7 = {…, -11,-4,3,10,17,…} = [-4] 7 = [10] 7 =…
Caratteri e Cifre p: corrispondente valore decimale del pattern P [1,…,m] (p = ∑ P [j]10 j, j = 1,…,m) t s : corrispondente valore decimale della sottostringa di lunghezza m t s = T[s+1,…,s+m], s=0,…,n-m Quindi p si può calcolare in tempo O(m) con la regola di Horner: p= P[m]+10(P[m-1]+10(P[m-2]+…+10(P[2]+10(P[1])…)
Calcolo delle T s t 0 può essere calcolato, come p, con la regola di Horner in tempo O(m) La sequenza t 1, t 2...t n-m può essere calcolata in tempo O(n-m) tenuto conto che t s+1 = 10(t s – 10 m-1 T[s+1])+T[s+m+1] Es: Sia T= ; m=5; t 0 = prima si sottrae la cifra più significativa da t s (-10 m-1 T[s+1]) (nell’esempio 3): – 3 x 10 4 = 1415 poi si trasla ilnumero di una posizione a sx (moltiplicazione per10) : 1415 x 10 = infine si inserisce l’appropiata cifra meno significativa (+ T[s+m+1]): =14152 Il calcolo delle potenze del 10 si può effettuare a priori in tempo O(m).
Versione base dell’algoritmo di Rabin-Karp Dato che s è uno spostamento valido se e solo se t s = p, tutti gli spostamenti validi si ottengono confrontando p con ogni t s Preelaborazione O(m) p e t 0 si calcolano in O(m) tempo le potenze di 10 si calcolano a priori in tempo O(m). Elaborazione(matching) O(m (n-m+1)) tutti gli (n-m) t s si calcolano in tempo costante uno dall’altro Problema: Se le dimensioni di P sono grandi, è irragionevole pensare che ogni operazione aritmetica sia costante
Se le dimensioni di P sono grandi…… p e tutti i t s si calcolano modulo un appropriato numero q in tempo O(n + m), dato che p, t 0 e tutte le ricorrenze possono essere eseguite modulo q Tipicamente come q viene scelto un numero primo tale che 10q sia rappresentabile dentro una parola della macchina e questo consente di eseguire tutti i calcoli in precisione aritmetica singola. In generale con un alfabeto d-ario si ha: t s+1 = (d(t s –T[s+1]h)+T[s+m+1]) modq dove h= d m-1 (mod q) è il valore della cifra “1” nella posizione più significativa di una porzione di testo di m cifre e q è scelto in modo che dq sia rappresentabile dentro una parola della macchina.
Ma c’è un inconveniente….. VALEt s congruo p(mod q) non implica t s = p t s non congruo p(mod q) implica t s ≠ p QUINDI se t s non congruo p(mod q) allora lo spostamento è non valido se t s congruo p(mod q) allora si deve controllare se P [1,…,m] = T[s+1,…,s+m] TEMPO DI ESECUZIONE nel caso peggiore: ((n-m+1)m) nel caso medio: O(n)+O(m( + n/q)) con = numero degli spostamenti validi