Esercizio - sottosequenza antipalindroma di lunghezza massima (compito del 9 luglio 2025, es. 2)
Fonte: compito di Algoritmi per l'Ingegneria, Ing. Informatica UniPD, 9 luglio 2025, seconda parte, esercizio 2 (17 punti).
Testo
Una stringa si dice antipalindroma se ha lunghezza pari e, per , soddisfa la relazione per . (Dunque è antipalindroma; le stringhe di lunghezza dispari non sono antipalindrome.)
Data in ingresso una arbitraria stringa di lunghezza definita su un qualche alfabeto , si vuole determinare la lunghezza di una Sottosequenza Antipalindroma di Lunghezza Massima (). (Si osservi che tale lunghezza sarà sempre un numero pari.)
- (a) [6 punti] Si provi una proprietà di sottostruttura ottima per il problema sullo spazio delle sottostringhe di .
- (b) [3 punti] Si fornisca una ricorrenza sulla lunghezza della di una generica sottoistanza .
- (c) [5 punti] Si fornisca lo pseudocodice bottom-up iterativo
COMPUTE_SALM(X)che, data in ingresso una stringa , restituisca la lunghezza di una SALM, argomentandone la correttezza. - (d) [3 punti] Sia il numero di confronti tra caratteri dell'alfabeto eseguiti dall'algoritmo sviluppato al punto (c). Si valuti esattamente.
Soluzione
Cosa significa "antipalindroma"
Gli estremi simmetrici sono sempre diversi: , , e così via. Se è dispari l'elemento centrale () dovrebbe essere diverso da sé stesso, impossibile: per questo le antipalindrome hanno lunghezza pari. Per esempio , e (coppie e ) sono antipalindrome; no, perché ; no, perché ha lunghezza dispari. È la variante "opposta" della sottosequenza palindroma più lunga (Allineamento di stringhe e sottosequenza palindroma più lungadue problemi di DP su stringhe con la stessa struttura della LCS. Allineamento ottimo di due stringhe di DNA con matrice di score S e penalità di gap g: C(i,j) = max{C(i-1,j-1) + s(x_i,y_j), C(i-1,j) + g, C(i,j-1) + g}, C(i,0) = i g, C(0,j) = j g; Theta(mn) tempo, spazio Theta(min{m,n}) con un solo vettore se serve solo il costo. Sottosequenza palindroma più lunga (LPS) sullo spazio delle sottostringhe X_(i..j): p(i,j) = 2 + p(i+1,j-1) se x_i = x_j, altrimenti max{p(i+1,j), p(i,j-1)}; scansione per diagonali, n(n-1)/2 confronti.Allineamento di stringhe e sottosequenza palindroma più lunga →), con la stessa struttura: si tolgono i due estremi, quindi lo spazio naturale è quello delle sottostringhe.
(a) Proprietà di sottostruttura ottima
Proprietà. Per ogni esiste una tale che:
- se , ;
- se e , ;
- se e , ;
- se e , allora , e è una ;
- se e , allora è una oppure una (la più lunga delle due).
Osservazione. Nel punto 4 si afferma che esiste una SALM che ha e come estremi, non che tutte le SALM li abbiano: l'enunciato più forte sarebbe falso. Per esempio in () le SALM sono , e , tutte di lunghezza , ma solo ha e . L'enunciato debole basta per un algoritmo corretto, come per la scelta greedy: serve che esista almeno una soluzione ottima con la proprietà.
Dimostrazione. I punti 1, 2 e 3 (sottostringhe di lunghezza o ) sono banali, e in quei casi è unica: una stringa di un solo carattere non ha sottosequenze antipalindrome non vuote (hanno lunghezza dispari); per due caratteri uguali nessuna coppia è diversa; per due caratteri diversi è antipalindroma e massima.
Sia ora (almeno caratteri) e sia una SALM qualsiasi di , con .
Punto 4, . Prima di tutto : altrimenti sarebbe una sottosequenza antipalindroma di lunghezza , più lunga. Quindi . Si costruisce a partire da sostituendo, se , il primo carattere con (usando l'indice ) e, se , l'ultimo con (usando l'indice ). Gli indici restano strettamente crescenti, quindi è una sottosequenza di della stessa lunghezza . è ancora antipalindroma: le coppie interne non sono cambiate, e la coppia esterna è diventata , di caratteri diversi (se nessuna sostituzione è avvenuta, era già , e la coppia era ). Quindi è una SALM con e . La sottostringa interna è antipalindroma e sottosequenza di . Se non fosse una SALM di , con il cut-and-paste si sostituirebbe con una SALM di : sarebbe antipalindroma (le coppie interne vengono da , quella esterna è ) e più lunga di , contraddizione.
Punto 5, . Sia una SALM di . Se la tesi è ovvia (anche le sottostringhe hanno SALM vuote). Altrimenti per l'antipalindromia, quindi e non possono essere entrambi uguali al comune valore . Se , l'indice non è usato () e è sottosequenza di ; se , e è sottosequenza di . In entrambi i casi è antipalindroma e per cut-and-paste deve essere una SALM della sottostringa in cui vive. Siccome le SALM delle due sottostringhe sono anche sottosequenze antipalindrome di , è la più lunga delle due.
(b) Ricorrenza
Sia , per :
I valori sono o ottenuti con incrementi di : sono tutti pari. Si vuole .
(c) Algoritmo bottom-up
Sia la lunghezza di . I casi base sono e . Per la cella dipende da (lunghezza ) e da e (lunghezza ): una scansione per diagonali di lunghezza crescente del triangolo superiore di una tabella è coerente con le dipendenze.
COMPUTE_SALM(X)
n <- length(X)
for i <- 1 to n-1 do
S[i, i] <- 0
if x_i != x_{i+1} then S[i, i+1] <- 2 else S[i, i+1] <- 0
S[n, n] <- 0 { diagonali l = 1 e l = 2 }
for l <- 3 to n do
for i <- 1 to n-l+1 do
j <- i + l - 1
if x_i != x_j then S[i, j] <- S[i+1, j-1] + 2
else S[i, j] <- MAX(S[i+1, j], S[i, j-1])
return S[1, n]Correttezza. Per induzione sulla lunghezza della sottostringa: le diagonali contengono i valori dei casi base della ricorrenza (b); per al momento in cui si calcola le celle , e appartengono a diagonali di lunghezza e , già complete e corrette per ipotesi induttiva, e l'assegnamento realizza la ricorrenza. La ricorrenza è corretta per la proprietà (a). Per il primo ciclo è vuoto e si restituisce . Valgono anche le scansioni "righe dalla alla " e "colonne con righe decrescenti". L'algoritmo è stato verificato in Python confrontandolo con l'enumerazione di tutte le sottosequenze su stringhe casuali (alfabeti di e simboli, lunghezza fino a ).
Esempio. (). Tabella (triangolo superiore, la diagonale vale ):
| 1: a | 2: b | 3: b | 4: a | 5: c | 6: a | 7: b | |
|---|---|---|---|---|---|---|---|
| 1: a | 0 | 2 | 2 | 2 | 4 | 4 | 6 |
| 2: b | 0 | 0 | 2 | 4 | 4 | 4 | |
| 3: b | 0 | 2 | 2 | 4 | 4 | ||
| 4: a | 0 | 2 | 2 | 4 | |||
| 5: c | 0 | 2 | 2 | ||||
| 6: a | 0 | 2 | |||||
| 7: b | 0 |
Per esempio perché ; (); (); e (). Una SALM di lunghezza è (coppie tutte diverse), sottosequenza di con indici .
Se si vuole solo la lunghezza, come per la LPS, bastano tre vettori (la diagonale corrente e le due precedenti): spazio lineare.
(d) Numero di confronti
L'algoritmo esegue un confronto tra caratteri di per ogni sottostringa di lunghezza , cioè per ogni coppia (i MAX confrontano interi, non caratteri):
Lo stesso risultato si ottiene per diagonali: confronti sulla diagonale (nel primo ciclo) e sulla diagonale , in tutto . Per l'esempio : confronti.
Versione ripasso
Testo. è antipalindroma se ha lunghezza pari e per ( lo è). Data di lunghezza , lunghezza di una SALM (sempre pari). (a) [6 punti] sottostruttura ottima sulle sottostringhe ; (b) [3 punti] ricorrenza su ; (c) [5 punti] COMPUTE_SALM(X) bottom-up con correttezza; (d) [3 punti] numero esatto di confronti tra caratteri.
- Struttura: gli estremi simmetrici sono diversi; si tolgono i due estremi, quindi spazio = sottostringhe (), come per la LPS (Allineamento di stringhe e sottosequenza palindroma più lungadue problemi di DP su stringhe con la stessa struttura della LCS. Allineamento ottimo di due stringhe di DNA con matrice di score S e penalità di gap g: C(i,j) = max{C(i-1,j-1) + s(x_i,y_j), C(i-1,j) + g, C(i,j-1) + g}, C(i,0) = i g, C(0,j) = j g; Theta(mn) tempo, spazio Theta(min{m,n}) con un solo vettore se serve solo il costo. Sottosequenza palindroma più lunga (LPS) sullo spazio delle sottostringhe X_(i..j): p(i,j) = 2 + p(i+1,j-1) se x_i = x_j, altrimenti max{p(i+1,j), p(i,j-1)}; scansione per diagonali, n(n-1)/2 confronti.Allineamento di stringhe e sottosequenza palindroma più lunga →).
- Proprietà (esiste una SALM di tale che): : ; : se , altrimenti; e : , e è una SALM di ; e : è una SALM di o di . L'enunciato è debole ("esiste una SALM"): basta, e il forte sarebbe falso.
- Prova (): (altrimenti è più lunga); si sostituisce il primo carattere con se e l'ultimo con se , e la coppia esterna resta diversa; l'interno è ottimo per cut-and-paste. (): quindi non entrambi uguali a , e si esclude l'indice oppure .
- Ricorrenza: ; se , altrimenti ; per : se , se . Tutti i valori sono pari.
COMPUTE_SALM(X)
n <- length(X)
for i <- 1 to n-1 do
S[i,i] <- 0
if x_i != x_{i+1} then S[i,i+1] <- 2 else S[i,i+1] <- 0
S[n,n] <- 0
for l <- 3 to n do for i <- 1 to n-l+1 do
j <- i + l - 1
if x_i != x_j then S[i,j] <- S[i+1,j-1] + 2 else S[i,j] <- MAX(S[i+1,j], S[i,j-1])
return S[1,n]- Correttezza: induzione sulla lunghezza ; dipende da diagonali e , già complete. Valgono anche righe da a o colonne con righe decrescenti.
- Esempio : , , , con (indici ).
- Confronti: uno per ogni : ( per ). Spazio , oppure lineare con tre vettori.
- Errori tipici: confondere il caso uguale e diverso rispetto alla LPS (qui permette di prendere entrambi gli estremi); inizializzare a quando i caratteri sono uguali; contare i
MAXcome confronti tra caratteri; dimenticare che le stringhe di lunghezza dispari non sono ammesse.