Scaricare la presentazione
La presentazione è in caricamento. Aspetta per favore
PubblicatoAlba Leone Modificato 9 anni fa
1
4/19/2015E. Giovannetti -- OI09.1 Olimpiadi di Informatica 2010 Giornate preparatorie Dipartimento di Informatica Università di Torino marzo 2010 14 – Programmazione dinamica: distanza minima fra due sequenze di caratteri. (versione 19/04/2015)
2
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.512 Distanza fra due sequenze di caratteri Si considerino le seguenti tre operazioni su una sequenza di caratteri (stringa): inserimento di un carattere all'interno della stringa (o in testa alla stringa); cancellazione di un carattere della stringa (con compatta- mento della stessa); sostituzione di un carattere della stringa con un altro carattere. Date due stringhe S1 ed S2, si definiscono: trasformazione di S1 in S2: una sequenza di operazioni dei tre generi precedenti che trasforma la sequenza S1 nella sequenza S2 ; distanza (minima) fra S1 ed S2: lunghezza della più corta trasformazione di S1 in S2, cioè numero mimimo di operazioni necessario per trasformare S1 in S2.
3
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.513 Esempio trasformazione (non minimale) di RISOTTO in PRESTO: RISOTTO 1cancella RISOTTO 2cancella ISOTTO 3cancella SOTTO 4cancella OTTO 5cambia T in SSTO 6inserisci PPSTO 7inserisci RPRSTO 8inserisci EPRESTO distanza (non minima) = 8
4
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.514 Esempi trasformazione minimale di RISOTTO in PRESTO: RISOTTO inserisci PPRISOTTO cambia I in EPRESOTTO cancella OPRESTTO (da PRESOTTO) cancella TPRESTO (da PRESTTO) distanza (minima) = 4 trasformazione di STUDENTE in LAUREATO: STUDENTE cambia S in LLTUDENTE cambia T in ALAUDENTE cambia D in RLAURENTE cambia N in ALAUREATE cambia E in OLAUREATO distanza (minima) = 5
5
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.515 Esempi trasformazione di ACQUA in VINO: ACQUA cancella ACQUA cambia C in VVQUA cambia Q in IVIUA cambia U in NVINA cambia A in OVINO distanza (minima) = 5
6
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.516 Esercizio Si specifichi, usando la tecnica della programmazione dinami- ca, l'algoritmo che, date due stringhe, trova la più corta tra- sformazione da una all'altra.
7
L’algoritmo ricorsivo Le due (sotto)stringhe terminano con lo stesso carattere: b 1 b 2...b i-1 c c 1 c 2...c j-1 c Allora la più corta trasformazione dalla prima alla seconda coincide con la più corta trasformazione b 1 b 2...b i-1 c 1 c 2...c j-1 Le due (sotto)stringhe terminano con caratteri diversi: b 1 b 2...b i-1 b c 1 c 2...c j-1 c Allora la più corta trasformazione dalla prima alla seconda è la più corta fra: b 1 b 2...b i-1 c 1 c 2...c j-1 seguita da CAMBIA b IN c; b 1 b 2...b i-1 b c 1 c 2...c j-1 seguita da INSERISCI c; b 1 b 2...b i-1 c 1 c 2...c j-1 c seguita da CANCELLA b; 19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.517
8
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.518 Esempio: trasf(“ RIS ", “ PRES ") = trasf (“ RI ", “ PRE ") distanze: d(“ RIS ", “ PRES ") = d(“ RI ", “ PRE ") PRESTO R Id S d O T T O stringa di partenza stringa di arrivo
9
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.519 Esempio: trasf(“ RISO ", “ PREST ") d(“ RISO ", “ PREST ") = min(d 1, d 2, d 3 ) + 1 PRESTO R I S d1d1 d2d2 Od3d3 T T O stringa di partenza stringa di arrivo
10
Base della ricorsione b 1 b 2...b i stringa vuota CANCELLA b 1, CANCELLA b 2,..., CANCELLA b i ; stringa vuota c 1 c 2...c j INSERISCI c 1, INSERISCI c 2,..., INSERISCI c j ; stringa vuota stringa vuota TRASFORMAZIONE NULLA Nota: Poiché in C(++) le stringhe e gli array sono indiciati a partire da 0, il numero di passi della trasformazione b 0 b 1...b i stringa vuota è i+1; analogamente il numero di passi della trasformazione stringa vuota c 0 c 1...c j è j+1; 19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5110
11
Trovare solo la distanza: funzione ricorsiva … string s, t; int m, n; int min3(int x, int y, int z) { int min = x <= y ? x : y; if(z < min) min = z; return min; } int dis(int i, int j) { if(i == -1) return j+1; if(j == -1) return i+1; if(s.at(i) == t.at(j)) return dis(i-1,j-1); else return 1+min3(dis(i-1,j-1),dis(i,j-1),dis(i-1,j)); } Nel main:... cout << dis(m-1, n-1); 19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5111
12
… inefficiente ! Soffre dello stesso grave difetto di fibonacci ricorsivo: il ricalcolo degli stessi valori rende “intrattabile” la complessità della procedura ! Come nel caso di fibonacci, occorre memorizzare i risultati delle chiamate ricorsive, in modo da non ricalcolare i valori già calcolati in qualche chiamata precedente. 19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5112
13
Ricorsione con memorizzazione Poiché le chiamate ricorsive sono della forma dist(i, j), con 0 i m-1, 0 j n-1, per memorizzarne i risultati serve una matrice di dimensioni m n. Inizializziamo tutti gli elementi di tale matrice ad un valore impossibile della distanza di editing, ad es. -1. Nella funzione dist, prima di andare ad eseguire il calcolo con le chiamate ricorsive, si controlla se il corrispondente elemento della matrice non contiene già il risultato (cioè è diverso da -1), e in tal caso lo si restituisce senza rifare il calcolo. Se invece il risultato viene calcolato, prima della return lo si memorizza nella matrice. 19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5113
14
Ricorsione con memorizzazione: codice C++. #define MAXL 100; string s, t; int m, n; int d[MAXL][MAXL];... int dis(int i, int j) { if(i == -1) return j+1; if(j == -1) return i+1; if(d[i][j] == -1) { if(s.at(i)==t.at(j)) d[i][j]= dis(i-1,j-1); else d[i][j] = 1+min3(dis(i-1,j-1),dis(i,j-1),dis(i-1,j)); } return d[i][j]; } 19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5114
15
Versione iterativa Come nel caso di fibonacci, l’algoritmo precedente si può scrivere in forma iterativa: la funzione dist diventa una procedura contenente un ciclo che calcola ad uno ad uno gli elementi della matrice, riga per riga. Alla fine la soluzione si troverà nell’elemento più a sinistra in basso, che è l’ultimo calcolato. È inoltre conveniente utilizzare una matrice (m+1) (n+1), dove la colonna 0 rappresenta la stringa vuota come stringa iniziale, la riga 0 la stringa vuota come stringa finale. Occorre allora premettere alle stringhe un carattere fittizio (ad es. un blank): s = “ ” + s; t = “ ” + t; La soluzione si troverà quindi in d[m][ n]. Prima del ciclo di calcolo vero e proprio bisogna inizializzare la prima riga e la prima colonna. 19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5115
16
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5116 Esempio: distanza ("RISOTTO", "PRESTO") PRESTO no 0ins 1ins 2ins 3ins 4ins 5ins 6 R del 1 I del 2 S del 3 O del 4 T del 5 T del 6 O del 7 stringa di partenza stringa di arrivo
17
Versione iterativa: codice C++. void dist() { // inizializzazione della riga 0 e della colonna 0 for(int i = 0; i <= m; i++) d[i][0] = i; for(int j = 1; j <= n; j++) d[0][j] = j; for(int i = 1; i <= m; i++) { for(int j = 1; j <= n; j++) { if(s.at(i) == t.at(j)) d[i][j] = d[i-1][j-1]; else d[i][j] = 1 + min3(d[i-1][j-1], d[i][j-1], d[i-1][j] ); } 19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5117
18
Trovare la trasformazione più corta. Se invece della sola distanza minima si vuole anche trovare la corrispondente sequenza di operazioni che trasforma la prima stringa nella seconda, occorre costruire, a fianco della matrice delle distanze, una matrice delle operazioni. Ciascun elemento della matrice contiene l’ultima operazione della trasformazione fra le due sottostringhe corrispondenti all’elemento. Alla fine, partendo dall’ultimo elemento a sinistra in basso si ricostruisce all’indietro il cammino percorso, dove la casella precedente dipende dal contenuto della casella corrente: CAMBIA : vai alla casella indietro in diagonale CANCELLA : vai alla casella sopra in verticale INSERISCI : vai alla casella a sinistra in orizzontale NO OP : vai alla casella indietro in diagonale 19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5118
19
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5119 PRESTO no 0ins 1ins 2ins 3ins 4ins 5ins 6 R del 1c 1no 1ins 2ins 3ins 4ins 5 I del 2 c 2 c 3... S del 3 c 3 no 2... O del 4 c 4 del 3 T del 5 T del 6 O del 7 stringa di partenza stringa di arrivo trasf("RISO", "PRES") = trasf("RIS", "PRES") + del O
20
Esempio di esecuzione Per semplicità, disegniamo le due matrici in sovrapposizione, come se fossero un’unica matrice in cui ogni casella contiene sia la distanza che l’operazione. 19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5120
21
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5121 PRESTO no 0ins 1ins 2ins 3ins 4ins 5ins 6 R del 1c 1 I del 2 S del 3 O del 4 T del 5 T del 6 O del 7 stringa di partenza stringa di arrivo trasf("R", "P") = [Cambia R in P], lungh = 1
22
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5122 PRESTO no 0ins 1ins 2ins 3ins 4ins 5ins 6 R del 1c 1no 1 I del 2 S del 3 O del 4 T del 5 T del 6 O del 7 stringa di partenza stringa di arrivo trasf("R", "PR") = trasf("", "P")
23
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5123 PRESTO no 0ins 1ins 2ins 3ins 4ins 5ins 6 R del 1c 1 no 1ins 2 I del 2 S del 3 O del 4 T del 5 T del 6 O del 7 stringa di partenza stringa di arrivo trasf("R", "PRE") = trasf("R", "PR") + ins E
24
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5124 PRESTO no 0ins 1ins 2ins 3ins 4ins 5ins 6 R del 1c 1no 1ins 2ins 3ins 4ins 5 I del 2 S del 3 O del 4 T del 5 T del 6 O del 7 stringa di partenza stringa di arrivo trasf("R", "PRESTO") = trasf("R", "PREST") + ins O
25
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5125 PRESTO no 0ins 1ins 2ins 3ins 4ins 5ins 6 R del 1c 1no 1ins 2ins 3ins 4ins 5 I del 2 c 2 S del 3 O del 4 T del 5 T del 6 O del 7 stringa di partenza stringa di arrivo trasf("RI", "P") = trasf("R", "") + cambia I in P
26
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5126 PRESTO no 0ins 1ins 2ins 3ins 4ins 5ins 6 R del 1c 1no 1ins 2ins 3ins 4ins 5 I del 2 c 2 S del 3 O del 4 T del 5 T del 6 O del 7 stringa di partenza stringa di arrivo trasf("RI", "PR") = trasf("R", "P") + cambia I in R
27
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5127 PRESTO no 0ins 1ins 2ins 3ins 4ins 5ins 6 R del 1c 1no 1ins 2ins 3ins 4ins 5 I del 2 c 2 c 3... S del 3 c 3 no 2... O del 4 c 4 del 3 T del 5 T del 6 O del 7 stringa di partenza stringa di arrivo trasf("RISO", "PRES") = trasf("RIS", "PRES") + del O
28
eccetera Esercizio: completare a mano la tabella. 19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5128
29
19/04/2015 23.41E. Giovannetti - AlgELab-09-10 - Lez.5129 Ricostruzione della sequenza di operazioni La sequenza si ricostruisce seguendo all'indietro le frecce.
Presentazioni simili
© 2024 SlidePlayer.it Inc.
All rights reserved.