La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

Programmazione dinamica: problema della sottosequenza più lunga

Presentazioni simili


Presentazione sul tema: "Programmazione dinamica: problema della sottosequenza più lunga"— Transcript della presentazione:

1 Programmazione dinamica: problema della sottosequenza più lunga
Esempio problema Algoritmo di ricerca esaustiva Caratterizzazione soluzione ottima Algoritmo ricorsivo Stategia Bottom-up Costruzione soluzione ottima

2 Problema della sottosequenza più lunga
Input: vengono dati in ingresso due sequenze x[1…m] e y[1…n] Problema: Cercare una sottosequenza più lunga che sia comune ad entrambe le sequenze. (Longest Common Subsequence, LCS) Verso sequenza x: A B C B D A B BCBA= LCS(x,y) y: B D C A B A Sottosequenza: una sottosequenza di una sequenza Z è un sottoinsieme strettamente crescente di Z

3 Algoritmo di bruta forza
Idea: per ogni sottosequenza di x[1…m] si controlla se è una sottosequenza di y[1…n]. Si memorizza la prima sottosequenza comune più lunga trovata. Analisi complessità: Ci vuole tempo O(n) per controllare se una sequenza è sottosequenza di y[1…n] 2m sottosequenze a partire da x[1…m] (basta pensare ad un vettore binario lungo m, ogni 1 vuol dire che l’elemento appartiene alla sottosequenza) Caso Peggiore: O(n 2m ) → tempo esponenziale

4 Soluzione in programmazione dinamica
Lo sviluppo di un algoritmo in programmazione dinamica può essere diviso in quattro fasi o passi: Caratterizzazione della struttura di una soluzione ottima. Definizione ricorsiva del valore di una soluzione ottima. Calcolo del valore di una soluzione ottima con una strategia bottom-up. Costruzione di una soluzione ottima a partire dalle informazioni calcolate.

5 Caratterizzazione soluzione ottima
Siano X[1…m] e Y[1…n] due sequenze e sia Z[z1, z2…zk] una LCS (sottosequenza più lunga), allora: Se xm = yn allora xm = yn = zk e Z[z1, z2…zk-1] è LCS di X[1…m-1] e Y[1…n-1] Se xm ≠ yn allora: se xm ≠ zk si ha che Z[z1, z2…zk] è LCS di X[1…m-1] e Y[1…n] se yn ≠ zk si ha che Z[z1, z2…zk] è LCS di X[1…m] e Y[1…n-1]

6 Caratterizzazione soluzione ottima
Dimostrazione: xm = yn Allora xm = yn = zk. Se non fosse così e xm = yn ≠ zk, allora si potrebbe estendere Z con xm = yn … assurdo! Si ha dunque che Z[1…k-1] è sottosequenza lunga k-1 sia di X[1…m-1] sia di Y[1…n-1]. Z[1…k-1] è anche la LCS di X[1…m-1] e di Y[1…n-1]. Se non fosse così ci sarebbe Z’[1…t] con t > k-1 LCS di X[1…m-1] e di Y[1…n-1]. Allora Z’ potrebbe essere esteso con xm = yn, formando una sottosequenza comune a X[1…m] e Y[1…n] lunga t+1 > k … assurdo!

7 Caratterizzazione soluzione ottima
Dimostrazione: 2. a. xm ≠ zk Z[1…k-1] è anche la LCS di X[1…m-1] e di Y[1…n]. Se non fosse così ci sarebbe Z’[1…t] con t > k LCS di X[1…m-1] e di Y[1…n]. Allora Z’ sarebbe una sottosequenza comune a X[1…m] e Y[1…n] lunga t > k … assurdo! 2. b. yn ≠ zk (speculare)

8 Definizione ricorsiva soluzione ottima
Siano X[1…i] e Y[1…j] due sequenze e sia Z[z1, z2…zk] una LCS (sottosequenza più lunga), allora: Se xi = yj allora xi = yj = zk e Z[z1, z2…zk-1] è LCS di X[1…i-1] e Y[1…j-1] Se xi ≠ yj allora: se xi ≠ zk si ha che Z[z1, z2…zk] è LCS di X[1…i-1] e Y[1…j] se yj ≠ zk si ha che Z[z1, z2…zk] è LCS di X[1…i] e Y[1…j-1]

9 Definizione ricorsiva soluzione ottima
Siano X[1…i] e Y[1…j] due sequenze e sia Z[z1, z2…zk] una LCS (sottosequenza più lunga) con lunghezza c[i,j], allora: X: 1 i m Y: 1 j n

10 Algoritmo ricorsivo Siano X[1…i] e Y[1…j] due sequenze e sia Z[z1, z2…zk] una LCS (sottosequenza più lunga) con lunghezza c[i,j], allora: LCS(X,Y,i,j) if i =0 and j= 0 return 0 if xi =yj then return LCS(X,Y,i-1,j-1)+1 else return max(LCS(X,Y,i-1,j) , LCS(X,Y,i,j-1)) Attenzione: Nel caso xi ≠ yj vengono generate due chiamate ricorsive (LCS(X,Y,i-1,j) e LCS(X,Y,i,j-1)) che possono generare sottoproblemi comuni.

11 Algoritmo ricorsivo m = 3 n = 4 Caso peggiore:
3,4 2,4 3,3 UGUALI ! Altezza m+n 1,4 2,3 2,3 3,2 1,3 2,2 1,3 2,2 Caso peggiore: xi ≠ yj sempre. Vengono generate due chiamate ricorsive (LCS(X,Y,i-1,j) e LCS(X,Y,i,j-1)) che possono generare sottoproblemi comuni.

12 Stategia bottom-up LCS(X,Y) m ← length[X] n ← length[Y] for i ← 1 to m
do c[i,0] ← 0 for j ← 1 to n do c[j,0] ← 0 do for j ← 1 to n do if xi =yj then c[i,j] ← c[i-1,j-1] +1 b[I,j] ← ‘diag’ else if c[i-1,j] ≥ c[i, j-1] then c[i,j] ← c[i-1,j] b[I,j] ← ‘up’ else c[i,j] ← c[i,j-1] b[I,j] ← ‘left’

13 Stategia bottom-up A B C B D A B 1 2 3 4 Tempo = Θ(m n)
1 2 3 4 Tempo = Θ(m n) Spazio = Θ(m n) = numero di sottosequenze per cui calcolare c[i,j] e b[i,j] B D C A B A

14 Costruzione di una soluzione ottima
B C B D A B 1 2 3 4 b[i,j] serve per ricavare andando a ritroso la LCS trovata. Ogni “diag” corrisponde ad un elemento della LCS. LCS = “BCBA” B D C A B A

15 Costruzione di una soluzione ottima
PRINT-LCS(b,X,Y,i,j) if i = 0 or j = 0 then return if b[i,j] = “diag” then PRINT-LCS(b,X,Y,i-1,j-1) print “xi” elseif b[i,j] = “up” then PRINT-LCS(b,X,Y,i-1,j) else PRINT-LCS(b,X,Y,i,j-1) Il tempo di esecuzione corrisponde a O(m+n), poiché al peggio deve ogni volta decrementare solo uno dei due valori (i oppure j).


Scaricare ppt "Programmazione dinamica: problema della sottosequenza più lunga"

Presentazioni simili


Annunci Google