Dati e Algoritmi I (Pietracaprina) Esercizi sul Text Processing

Documenti analoghi
Dati e Algoritmi 1: A. Pietracaprina. Text Processing

Dati e Algoritmi I (Pietracaprina) Esercizi sulle Nozioni di Base

Dati e Algoritmi I (Pietracaprina) Esercizi sulle Nozioni di Base

Nozioni di base (II Parte)

Dati e Algoritmi I (Pietracaprina) Esercizi su Alberi Binari di Ricerca e (2,4)-Tree

Dati e Algoritmi I (Pietracaprina) Esercizi sugli Alberi

Dati e Algoritmi I (Pietracaprina) Esercizi svolti sull Ordinamento

Calcolare x n = x x x (n volte)

Esercizi per il corso di Algoritmi, anno accademico 2011/12

Calcolare lo Span di un array di numeri

Elezione di un leader in una rete ad anello

Nell informatica esistono alcuni problemi particolarmente rilevanti, poiché essi:

Problemi di ricerca in insiemi ordinati

Algoritmi e Strutture di Dati (3 a Ed.) String matching. Alan Bertossi, Alberto Montresor

Note per la Lezione 6 Ugo Vaccaro

Algoritmi e Strutture Dati. Capitolo 4 Ordinamento: Selection e Insertion Sort

Informatica Generale Andrea Corradini Gli algoritmi e la risoluzione di problemi

Introduzione agli algoritmi Prova di esame del 19/9/2016 Prof.sse E. Fachini - R. Petreschi. Parte prima

Esercizi vari. Alberto Montresor. 19 Agosto, 2014

Problemi, istanze, soluzioni

Algoritmi e Strutture di Dati I 1. Algoritmi e Strutture di Dati I Massimo Franceschet francesc

Dati e Algoritmi I (Pietracaprina) Esercizi svolti sui Grafi

Un algoritmo realizza una relazione funzionale tra i valori di input e quelli di output

Informatica Generale Andrea Corradini Algoritmi: ordinamento per inserimento e ricorsione

Algoritmi e Strutture Dati. Capitolo 4 Ordinamento

In questa lezione. Il Mergesort: primo esempio di applicazione della tecnica divide et impera analisi tempo di esecuzione del Mergesort

Indice. 1 Introduzione 2. 2 Algoritmo di compressione LZ78 3

Note per la Lezione 17 Ugo Vaccaro

Esercizi Capitolo 10 - Code con priorità e insiemi disgiunti

Silvia Rossi. Algoritmi di Ricerca. Informatica. Lezione n. Parole chiave: Ricerca Lineare Ricerca Binaria. Corso di Laurea:

Algoritmi greedy. Gli algoritmi che risolvono problemi di ottimizzazione devono in genere operare una sequenza di scelte per arrivare alla soluzione

Esercizi Capitolo 10 - Code con priorità e insiemi disgiunti

Algoritmi e Strutture Dati - II modulo Soluzioni degli esercizi

In questa lezione. Heap binario heapsort. [CLRS10] cap. 6, par Prof. E. Fachini - Intr. Alg.

Lezione 4 Ugo Vaccaro

Rappresentazione degli algoritmi

Problemi e algoritmi

Argomenti della lezione. Introduzione agli Algoritmi e alle Strutture Dati. Lista Lineare. Lista Lineare come Tipo di Dato Astratto

Lo sviluppo di un semplice programma e la dimostrazione della sua correttezza

Ing. Lorenzo Vismara

Informatica

Problemi e algoritmi. Il che cosa e il come. F. Damiani - Alg. & Lab. 04/05 (da U. de' Liguoro - Alg. & Spe. 03/04)

Problemi e algoritmi. Il che cosa ed il come. Il che cosa ed il come. Il che cosa e il come

Diagramma a blocchi per la selezione, in un mazzo di chiavi, di quella che apre un lucchetto

a.a Codice corso: 21012

PROBLEMA DEI CAMMINI MINIMI [CORMEN ET AL. CAP. 24] Il costo di cammino minimo da un vertice u ad un vertice v è definito nel seguente modo:

Sommario. Problemi di decisione, di ricerca e di ottimizzazione: come sono legate le complessità delle diverse versioni dei problemi?

ESERCITAZIONI DI INTRODUZIONE AGLI ALGORITMI (A.A. 08/09)

Prova di Algoritmi e s.d. (1o anno) 17 Settembre TESTO e RISPOSTE

A.A CORSO DI ALGEBRA 1. PROFF. P. PIAZZA, E. SPINELLI. SOLUZIONE ESERCIZI FOGLIO 5.

Programmazione I - corso B a.a prof. Viviana Bono

Algoritmi di Ricerca. Esempi di programmi Java

Costrutti di Programmazione Strutturata. Informatica 1 / 22

In questa lezione: correttezza del mergesort Analisi del mergesort: relazioni di ricorrenza e alberi della ricorsione

Calcolare il massimo di una lista

Esercizi Capitolo 7 - Hash

Dizionari Liste invertite e Trie

Logica per la Programmazione

Soluzioni del compito di esonero di Algebra

Tecniche di prova per induzione

Laboratorio di Algoritmi e Strutture Dati

Complementi di Algoritmi e Strutture Dati. Soluzioni prova scritta 7 giugno 2017

Si imposti la relazione di ricorrenza che ne descrive la complessità e la si risolva utilizzando il metodo della sostituzione.

come segue: data una collezione C di elementi e una un elemento che verifica la proprietà P

Grafi: visita generica

11.4 Chiusura transitiva

Esercizi Capitolo 11 - Strutture di dati e progettazione di algoritmi

Algoritmi greedy. Gli algoritmi che risolvono problemi di ottimizzazione devono in genere operare una sequenza di scelte per arrivare alla soluzione

UNIVERSITÀ di ROMA TOR VERGATA

Fondamenti di Informatica. Algoritmi di Ricerca e di Ordinamento

Esercitazione 6. Array

Appendice B. Algoritmi e Complessità

Sommario. Problemi di decisione, di ricerca e di ottimizzazione: come sono legate le complessità delle diverse versioni dei problemi?

Esercizi di Algoritmi e Strutture Dati

Algoritmi Greedy. Tecniche Algoritmiche: tecnica greedy (o golosa) Un esempio

In questa lezione. Code di priorità. [CLRS01] cap. 6 da pag. 114 a pag Prof. E. Fachini - Intr. Alg. lunedì 17 settembre 2012

Logica per la Programmazione

Logica per la Programmazione

Esempio: quanto mi piace questo corso! qufuafantofo mifi pifiafacefe qufuefestofo coforsofo!

Esercizi svolti a lezione

Testing, correttezza e invarianti

Il problema delle azioni

1) Data la seguente istanza di TSP (grafo completo con 5 nodi): c 12 = 52; c 13 = 51; c 14 = 40; c 15 = 53; c 23 = 44;

Verifica dei programmi

STRUTTURE DI CONTROLLO DEL C++

Aniello Murano Problemi non decidibili e riducibilità

Algoritmi 2 - Dr. Simone Faro - Esercizi sulle Tabelle Hash 1

Note per la Lezione 18 Ugo Vaccaro

Esercizi di Algoritmi e Strutture Dati

Sui Linguaggi Regolari: Teorema di Kleene - Pumping Lemm

Suffix Trees. Docente: Nicolò Cesa-Bianchi versione 21 settembre 2017

1 Calcolo approssimato della serie di Fourier

6) Descrivere con un diagramma a blocchi un algoritmo che legga da input due numeri ne calcoli il prodotto in termini di somme ripetute.

Algoritmi di Ricerca. Esempi di programmi Java

Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano. Usa la tecnica del divide et impera:

usiamo lettere minuscole per i nomi simbolici utilizzati nello stato e negli algoritmi; usiamo lettere maiuscole per indicare costanti generiche

Riassumiamo le proprietà dei numeri reali da noi utilizzate nel corso di Geometria.

Progetto e analisi di algoritmi

Transcript:

Dati e Algoritmi I (Pietracaprina) Esercizi sul Text Processing

Dati e Algoritmi I (Pietracaprina): Esercizi 1 Problema 1. Sia T un testo di n caratteri e P un pattern di m n caratteri e si supponga che i caratteri di P siano tutti distinti. Dimostrare che l algoritmo findbrute esegue al più 2 confronti per ogni posizione T [k] di T. Consideriamo una posizione arbitraria T [k] del testo T e supponiamo che il primo confronto che coinvolge T [k] sia con P [j], per un qualche j, con 0 j < m. Se j = 0 il confronto è chiaramente l ultimo che coinvolge T [k] in quanto il ciclo while interno al ciclo for toccherà T [k] solo una volta, e la prossima iterazione del for partirà da T [k+1]. Se invece j > 0 significa che il primo confronto che coinvolge T [k] avviene nell iterazione i del for, con i = k j. In tale iterazione T [k] viene toccato solo una volta. Inoltre, dato che i caratteri di P sono tutti diversi, le successive j 1 iterazioni del for, con i = k j + 1, k j + 2,..., k 1, falliscono al primo confronto e non arrivano a toccare T [k]. Quindi T [k] verrà toccato una seconda volta nella iterazione i = k, quando viene confrontato con P [0]. Per quanto argomentato sopra, questa sarà l ultima iterazione in cui T [k] è coinvolto in un confronto. Problema 2. Sia T un testo di n caratteri. a. Progettare un algoritmo che, usando un unico ciclo, trova la posizione i in cui inzia la più lunga sottostringa di T fatta di caratteri uguali. (Ad esempio per T = aabaaabccbb l algoritmo deve restitutire la posizione i = 3 relativa all inizio della sottostringa aaa). b. Analizzare la complessità in tempo dell algoritmo. (Per avere punteggio pieno l algoritmo deve avere complessità O (n).) c. Trovare un invariante per il ciclo che serva per provare la correttezza dell algoritmo. a. Un possibile algoritmo è il seguente Algoritmo MaxSubstringEq(T) input Testo T, con T =n output indice i 0 di inizio della sottostringa piu lunga di T di caratteri uguali i 0; k 1; max-k 1; for j 1 to n-1 do { if (T[j] = T[j-1]) then { k k+1; if (k > max-k) then { i j-k+1; max-k k; else k 1; return i

Dati e Algoritmi I (Pietracaprina): Esercizi 2 b. Dato che fuori dal ciclo for e in ogni sua iterazione si esegue un numero costante di operazioni, la complessità è proporzionale al numero di iterazioni del ciclo for, ed è quindi O (n). c. Un invariante che vale alla fine di ogni iterazione del ciclo, e che alla fine del ciclo garantisce la correttezza dell algoritmo, è il seguente: una sottostringa di T [0... j] fatta di caratteri uguali e di lunghezza massima inizia alla posizione i ed è lunga max-k; la più lunga sottostringa di T fatta di caratteri uguali che termina in T [j] è T [j k + 1... j], ed è quindi lunga k. Problema 3. Si consideri un testo T e un pattern P, con T = n, P = m n e si supponga che P [0] P [i], 1 i m 1. a. Modificare findbrute per risolvere efficientemente le istanze del problema di pattern matching che soddisfano queste ipotesi. L algoritmo modificato deve contenere un solo ciclo e deve avere possibilmente complessità lineare. b. Analizzare la complessità dell algoritmo c. Analizzare la correttezza dell algoritmo a. La modifica a findbrute si basa sulle seguenti idee. Anzitutto, si progetta un unico ciclo che utilizza due variabili i e j per scandire testo e pattern rispettivamente. Le variabili avanzano se T [i] = P [j], mentre appena si verifica un mismatch (T [i] P [j]), la variabile j viene reimpostata a 0. Per sfruttare le ipotesi fatte sul pattern, quando si verifica il mismatch la variabile i viene lasciata inalterata. Supponendo infatti che T [i] P [j] ma T [i j... i 1] = P [0... j 1], sarebbe inutile provare ad allineare il pattern a partire da T [l], con i j < l < i, in quanto quelle posizioni non possono contenere il carattere P [0] e produrrebbero subito un mismatch. Lo pseudocodice dell algoritmo è il seguente:

Dati e Algoritmi I (Pietracaprina): Esercizi 3 Algoritmo BFMPlus(T,P) input Testo T, e pattern P, con T =n e [P]=m, e P[0] P[j] 0<j<m output indice i tale P=T[i... i-m+1], se esiste, altrimenti -1 i 0; j 0; while (i<n) do { if (P[j] = T[i]) then { i i+1 j j+1 if (j=m) then return (i-j) else if (j>0) then j 0; else i i+1 return -1 b. Dato che in ogni iterazione del while si esegue un numero costante di operazioni, la complessità risulta proporzionale al numero di iterazioni del while. Per dare un limite superiore a tale numero, si osservi che i aumenta di 1 almeno ogni due iterazioni e non decresce mai. Di conseguenza la complessità di BFMPlus è O (n). c. La correttezza è basata sul seguente invariante che deve valere alla fine di ogni iterazione del while. Siano P [j] e T [i] i prossimi caratteri di pattern e testo da confrontare. Allora si ha che P T [l... l + m 1], 0 l < i j P [0... j 1] = T [i j... i 1] Si noti che è, nella sostanza, lo stesso invariante dell algoritmo findbrute. L invariante vale all inzio del ciclo per vacuità. Supponiamo che valga all inizio di una generica iterazione (ovvero alla fine della precedente) e dimostriamo che rimane vero anche alla fine dell iterazione. Distinguiamo diversi casi Caso 1 (P [j] = T [i]). In questo caso, l algoritmo incrementa i e j, ed entrambe le proprietà dell invariante rimangono vere. La prima infatti non cambia, mentre per la seconda la corrispondenza tra testo e pattern si estende di un carattere. Caso 2 (P [j] T [i] e j > 0). L assunzione fatta su P garantisce e l invariante che valeva all inizio della iterazione, garantiscono che non si può trovare un occorrenza del pattern nel testo a partire da un indice < i. Ponendo quindi j = 0 e non cambiando i, l invariante continua a valere. Caso 3 (P [j] T [i] e j = 0). Chiaramente, incrementando i di 1 l invariante continua a valere. Consideriamo adesso la fine del while. Se l ultima iterazione è quella in cui si è trovato il pattern (quindi si ha che j = m), allora l algoritmo restituisce correttamente l indice di inizio di tale pattern nel testo. Se invece si esce dal while con i = n e j < m, allora la prima proprietà dell invariante garantisce che non ci sono occorrenze di P in T e l algoritmo restituisce correttamente -1.

Dati e Algoritmi I (Pietracaprina): Esercizi 4 Problema 4. Dati un testo T e un pattern P, con T = n, P = m n, si vogliono trovare tutte le occorrenze di P in T. a. Modificare l algoritmo findkmp per risolvere il problema b. Analizzare la complessità dell algoritmo c. Analizzare la correttezza dell algoritmo a. Stabiliamo che l algoritmo restituisca una lista L contenente tutti gli indici i tali che P = T [i... i + m 1]. Per determinare efficientemente L basta modificare findkmp in modo che continui ad andare avanti anche dopo aver trovato il pattern. In particolare, se a un certo punto confrontiamo T [i] e P [j], con j = m 1, e troviamo corrispondenza, si incrementa i di 1, si aggiunge l indice i m alla lista L e si imposta j a f(m 1). In questo modo, si testerà il prossimo shift del pattern sotto il testo che può portare a un matching completo. Lo pseudocodice è il seguente: Algoritmo AllOccurrences(T,P) input Testo T, e pattern P, con T =n e [P]=m output Lista L contenente gli indici i tali che P=T[i... i+m-1] f computefailkmp i 0; j 0; L lista vuota while (i<n) do { if (P[j] = T[i]) then { i i+1 j j+1 if (j=m) then { aggiungi i-j a L j f(m-1) else if (j>0) then j f(j-1) else i i+1 return L b. Lo stesso argomento usato per analizzare findkmp dimostra che l algoritmo AllOccurrences ha complessità Θ (n + m). c. Assumendo che il calcolo della failure function sia corretto, l analisi di correttezza si basa sul seguente invariante che deve valere alla fine di ogni iterazione del while. Siano P [j] e T [i] i prossimi caratteri di pattern e testo da confrontare. Allora si ha che L contiene tutti gli indici l tali che P = T [l... l + m 1], con 0 l < i j. P [0... j 1] = T [i j... i 1].

Dati e Algoritmi I (Pietracaprina): Esercizi 5 L invariante vale all inzio del ciclo per vacuità. Supponiamo che valga all inizio di una generica iterazione (ovvero alla fine della precedente) e dimostriamo che rimane vero anche alla fine dell iterazione. Distinguiamo diversi casi Caso 1 (P [j] = T [i]): Se j < m 1, l algoritmo incrementa i e j, ed entrambe le proprietà dell invariante rimangono vere. La prima infatti non cambia, mentre per la seconda la corrispondenza tra testo e pattern si estende di un carattere. Se invece j = m 1, l algoritmo incrementa i, aggiunge i m a L, e imposta j = f(m 1). Entrambe le proprietà dell invariante rimangono vere grazie alla failure function. Infatti, con i nuovi valori di i e j si vede che L contiene tutti gli indici l < i j tali che P = T [l... l + m 1] (in particolare conterrà anche l indice i m), e che P [0... j 1] = T [i j... i 1]. Caso 2 (P [j] T [i] e j > 0): Si usa lo stesso argomento dell analisi di findkmp. Caso 3 (P [j] T [i] e j = 0): Si usa lo stesso argomento dell analisi di findkmp. Consideriamo adesso l ultima iterazione del while. Alla fine di questa iterazione abbiamo che i = n e j < m (si noti che anche se l algoritmo avesse trovato il pattern alla fine j sarebbe impostato a f(m 1) m 1). Valendo l invariante, si ha che la prima proprietà implica immediatamente la correttezza dell algoritmo. Problema 5. (Esercizio C-12.19 del testo [GTG14]) Dati un testo T e un pattern P, con T = n, P = m, si vogliono trovare inizio e lunghezza del più lungo prefisso di P in T in tempo O (n + m). a. Progettare un algoritmo per risolvere il problema b. Far vedere che la complessità dell algoritmo è O (n + m) c. Analizzare la correttezza dell algoritmo a. Modifichiamo l algoritmo findkmp in modo che durante la sua esecuzione tenga traccia del più lungo prefisso di P osservato come sottostringa di T. A tal fine, utilizziamo due variabili k e l che in ogni momento mantengano, rispettivamente, la lunghezza del più lungo prefisso osservato sino a quel momento e il suo punto di inizio. Ovviamente, se a un certo punto tutto P viene trovato in T, quello sarà il più lungo prefisso cercato e l algoritmo può terminare. Lo pseudocodice è il seguente: Algoritmo MaxPrefix(T,P) input Testo T, e pattern P, con T =n e [P]=m output lunghezza (k) e inizio (l) del piu lungo prefisso di P sottostringa di T f compute FailKMP i 0; j 0; k 0; l -1 while (i<n) do {

Dati e Algoritmi I (Pietracaprina): Esercizi 6 if (P[j] = T[i]) then { if (j+1>k) then { k j+1; l i-j i i+1 j j+1 if (j=m) then return (k,l) else if (j>0) then j f(j-1) else i i+1 return (k,l) b. Lo stesso argomento usato per analizzare findkmp dimostra che l algoritmo MaxPrefix ha complessità Θ (n + m). c. Assumendo che il calcolo della failure function sia corretto, l analisi di correttezza si basa sul seguente invariante che deve valere alla fine di ogni iterazione del while. Siano P [j] e T [i] i prossimi caratteri di pattern e testo da confrontare. Allora si ha che un prefisso di P di lunghezza massima che sia sottostringa di T [0... i 1] a partire da una posizione i j ha lunghezza k e inizia in T [l]; P [0... j 1] = T [i j... i 1] Il completamento della prova è lasciato come esercizio Problema 6. Si vuole semplificare l algoritmo findkmp, nel caso in cui i caratteri del pattern P siano ordinati alfabeticamente (supponendo che sull alfabeto sia definito un qualche ordinamento). a. Determinare la failure function per il pattern P = aaabbcdd. b. Usando l intuizione ricavata dal punto precedente, individuare le caratteristiche particolari della failure function di un qualsiasi pattern ordinato alfabeticamente. c. Dire come può essere modificato l algoritmo findkmp in modo da utilizzare spazio aggiuntivo costante (oltre allo spazio richiesto da T e P ), nel caso in cui P sia ordinato alfabeticamente. a. La failure function per P = aaabbcdd è f(j) = j per 0 j 2 f(j) = 0 per 2 < j < 8 b. In generale si può facilmente verificare che se P è ordinato alfabeticamente e se k è il massimo indice tale che P [k] = P [0], allora la failure function è: f(j) = j per 0 j k f(j) = 0 per k < j < m

Dati e Algoritmi I (Pietracaprina): Esercizi 7 c. Nell algoritmo findkmp il calcolo della failure function per il pattern P diventa semplicemente la determinazione del massimo indice k tale che P [k] = P [0], che richiede una scansione di P e solo spazio costante per memorizzare k. Infine si sostituisce all istruzione j f(j-1), l istruzione if (j-1 k) then j j-1 else j 0 Problema 7. Dati un testo T e un pattern P, con T = n, P = m n, si vuole determinare se P è sottostringa circolare di T, cioè se: P è sottostringa ( normale ) di T ; oppure P si può ottenere concatenando un suffisso di T a un prefisso di T. (Ad esempio, DBA è sottostringa circolare di ABCDDB.) Progettare un algoritmo che risolva il problema in tempo O (n). È sufficiente creare un testo T di lunghezza n + m 1 concatenando T con il suo prefisso di lunghezza m 1. È immediato vedere che un pattern P di lunghezza m è sottostringa circolare di T se e solo se P è sottostringa di T. Si applica quindi l algoritmo findkmp a T e P. La creazione di T contribuisce una complessità O (n), mentre l esecuzione di findkmp con T e P contribuisce una complessità O (n + m). Essendo m n si ha che la complessità totale è O (n). Problema 8. Si consideri l algoritmo computefailkmp visto a lezione per il calcolo della failure function di un pattern P. Dimostrare che l algoritmo è corretto usando il seguente invariante per il ciclo while: f(0), f(1),..., f(i 1) sono stati calcolati correttamente f(i) j + 1 P [0... j 1] = P [i j... i 1] Verifichiamo anzitutto che l invariante è vero alla fine di ciascuna iterazione del while. All inizio del ciclo (i = 1, j = 0) l invariante vale dato che f(0) = 0 è stata già calcolata, f(1) 1, dalla definizione di failure function, e la terza proprietà è vera per vacuità, dato che j = 0. Supponiamo che sia vero alla fine di una certa iterazione e consideriamo l iterazione successiva, ovvero l iterazione in cui si confrontano P [i] e P [j]. Distinguiamo diversi casi: Caso 1 (P [j] = P [i]). In questo caso, le relazioni f(i) j + 1, P [0... j 1] = P [i j... i 1], e P [j] = P [i], implicano immediatamente che f(i) = j + 1 e che P [0... j] = P [i j... i]. Inoltre, se f(i) = j + 1 deve essere necessariamente f(i + 1) j + 2. Di conseguenza, l assegnamento f(i) j + 1 e l incremento di i e di j rendono vero l invariante alla fine della iterazione.

Dati e Algoritmi I (Pietracaprina): Esercizi 8 Caso 2 (P [j] P [i] e j > 0). In questo caso possiamo dedurre che f(i) j. Il fatto che P [0... j 1] = P [i j... i 1] e la definizione di failure function implicano che il prefisso P [0... f(j 1) 1] coincide con la sottostringa P [i f(j 1)... i 1] e che P [0... f(j 1) 1] è il più lungo prefisso che, esteso di un carattere, ha una qualche speranza di diventare suffisso di P [1... i]. Quindi, l assegnamento j f(j 1) mantiene verificato l invariante. Caso 3 (P [j] P [i] e j = 0). In questo caso possiamo dedurre che f(i) 0. Quindi, l assegnamento f(i) 0 e l incremento di i mantengono verificato l invariante. Consideriamo adesso la fine dell ultima iterazione del while (i = m). La prima proprietà dell invariante assicura che tutti i valori della failure function sono stati correttamente calcolati. L algoritmo quindi risulta corretto.