Documente Academic
Documente Profesional
Documente Cultură
Algoritmul ineficient
Algoritmul Rabin-Karp
Algoritmul Knuth-Morris-Pratt
Rezumat
Implementri sugerate
Probleme propuse
Soluiile problemelor
Capitolul
21
n cadrul acestui capitol vom prezenta modul n care se poate realiza cutarea unui
subir ntr-un ir.
Vom considera un ir de lungime N i vom verifica dac acesta conine un subir
de lungime M (M N). n cazul n care subirul apare n ir, vom determina poziia la
care ncepe acesta.
Vom ncepe cu un algoritm simplu, care va determina toate apariiile subirului, dar
care este ineficient. Vom continua cu doi algoritmi mult mai rapizi i anume algoritmul Rabin-Karp i algoritmul Knut-Morris-Pratt.
285
Algoritm Potrivire(ir,subir):
Acest algoritm va funciona corect, indiferent de tipul irului i al subirului. Aadar, el poate fi aplicat indiferent de tipul elementelor coninute de ir i subir, atta
timp ct irul i subirul conin acelai tip de elemente. Ca urmare, vom putea folosi
acest algoritm pentru iruri de caractere, iruri de numere etc.
N N2
= O (N 2 )
= O
= O
O N
2
4
2
4
4
286
287
Se observ acum c o valoare ts+1 poate fi calculat pe baza valorii ts foarte simplu,
folosind formula:
ts+1 = 10 (ts 10m-1 Ts+1) + Ts+m-1.
Prin scderea valorii 10m-1 Ts+1 se elimin prima cifr a numrului, prin nmulirea
cu zece se adaug cifra 0 la sfritul numrului, iar prin adunarea valorii Ts+m-1 cifra 0
este nlocuit cu cifra corect.
S considerm irul 2457 i subirul 13. Valoarea p va fi 13, iar valoarea t0 va fi 24.
Pe baza formulei anterioare vom obine:
t1 = 10 (24 102-1 2) + 5 = 10 (24 20) + 5 = 10 4 + 5 = 40 + 5 = 45.
Aadar, putem calcula n timp constant fiecare valoare ts i apoi o putem compara
cu valoarea p. Ca urmare, ordinul de complexitate al algoritmului va deveni O(n m +
m + m) = O(m + n). Iniial vom calcula valorile t0 i p, ambele ntr-un timp de ordinul
O(m). Ulterior, vom determina cele n m valori ts, ntr-un timp total de ordinul O(n
m).
Din nefericire, acest algoritm are un inconvenient i anume faptul c valorile p i ts
sunt numere foarte mari. Din acest motiv nu vom putea lucra efectiv cu astfel de valori
dect dac simulm operaii cu numere mari. Datorit faptului c aceste valori au m cifre, apare un factor suplimentar O(m), deci obinem un ordin de complexitate O(m n).
288
tru aceasta vom compara efectiv subirul P cu subirul din T care ncepe la poziia s +
1.
Teoretic, testul respectiv ar putea fi necesar la fiecare pas. Ordinul de complexitate
al testului este O(m) deci, n cazul cel mai nefavorabil, ajungem la ordinul de complexitate O((n m) (m + n)) = O(n2 m2).
Practic, dac valoarea q este bine aleas (un numr prim ct mai mare) ansa apariiei unei false potriviri este foarte redus (1 / q). De aceea, numrul comparaiilor efectuate inutil datorit unor false potriviri va fi de aproximativ (n m + 1) / q.
Aadar, pentru cazul mediu, algoritmul va funciona n timp liniar.
289
sfrit dac
sfrit dac
ts+1 rest[(b (ts irs+1 x) + irs+M+1) / q]
sfrit pentru
sfrit algoritm
290
291
pentru i 1, N execut:
ct timp (q > 0) i (subirq+1 iri) execut:
q q
sfrit ct timp
dac subirq+1 = iri atunci
q q + 1
sfrit dac
dac q = M atunci
scrie 'Subirul apare la poziia ', i - m, '.'
q q
sfrit dac
sfrit pentru
sfrit algoritm
21.4. Rezumat
n cadrul acestui capitol am prezentat trei modaliti prin care pot fi determinate apariiile unui subir ntr-un ir. Toi cei trei algoritmi determin toate apariiile, dar pot fi
uor modificai pentru a determina prima sau ultima apariie.
Am nceput cu un algoritm simplu, dar ineficient care poate fi utilizat pentru orice
tip de iruri. Am continuat cu algoritmul Rabin-Karp, un algoritm care impune anumite limitri pentru structura irurilor. Cu aceast ocazie am artat modul n care se utilizeaz aritmetica modular pentru mbuntirea timpului de execuie. Am artat c,
dei pentru cel mai nefavorabil caz timpul de execuie al algoritmului este ptratic,
pentru cazul mediu acesta devine liniar, motiv pentru care acest algoritm poate fi utilizat cu succes n majoritatea cazurilor.
n final, am prezentat algoritmul KMP care ruleaz n timp liniar n orice situaie.
Am introdus noiunea de funcie prefix i am artat modul n care aceasta se poate utiliza pentru a verifica apariiile unui subir ntr-un ir.
292
293
Date de intrare
Prima linie a fiierului de intrare SCOOBY.IN conine un ir de litere ale alfabetului
englezesc, reprezentnd literele desentate pe mrgele. Cea de-a doua linie conine un
alt ir de litere ale alfabetului englezesc care reprezint un cuvnt pe care Scooby l
caut pe brar.
Date de ieire
Fiierul de ieire SCOOBY.OUT va conine o singur linie pe care se va afla un singur
numr, reprezentnd numrul de ordine al mrgelei de la care ncepe cuvntul cutat.
n cazul n care cuvntul nu se afl pe brar, valoarea acestui numr va fi 1.
Restricii i precizri
1 N 5000;
cuvntul cutat va conine cel mult N litere;
cuvntul cutat poate aprea pe brar de mai multe ori; n acest caz se poate
alege oricare dintre poziiile la care ncepe cuvntul;
se va face distincie ntre literele mici i literele mari.
Exemple
SCOOBY.IN
ScoobyDoobyDoo
Doo
SCOOBY.OUT
7
SCOOBY.IN
abcd
dabc
SCOOBY.OUT
4
SCOOBY.IN
AlphaBetaGamma
Beta
SCOOBY.OUT
-1
21.6.2. Venus
Descrierea problemei
n timpul tratativelor, n urma crora se va stabili cine are dreptul de a coloniza satelitul Titan, ambasadorul venusian a primit un mesaj codificat care prea s fi fost trimis
de ctre Guvernul Planetar de pe Venus.
294
Evident, el trebuie s verifice dac mesajul este autentic i dup aceea s aplice un
algoritm de decodificare foarte simplu. Dac mesajul este autentic, atunci el va conine, ntr-un anumit loc, o semntur pe care venusianul o cunoate.
Dup identificarea semnturii, ea va fi eliminat din mesaj, iar restul mesajului va
fi destul de uor de citit. Litera 'a' va fi nlocuit de litera 'z', litera 'b' va fi nlocuit de litera 'y' i aa mai departe.
Va trebui s verificai dac mesajul este autentic i, n caz afirmativ, s determinai
mesajul scris de venusieni.
Date de intrare
Prima linie a fiierului de intrare VENUS.IN conine mesajul care pare a fi sosit de la
guvernul venusian. Cea de-a doua linie a fiierului va conine semntura care trebuie
s apar n mesaj.
Date de ieire
Fiierul de ieire VENUS.OUT va conine mesajul decodificat, dac acesta este autentic
sau doar caracterul '*' n caz contrar.
Restricii i precizri
1 N 5000;
semntura va conine cel mult N 2 litere;
semntura poate aprea n mesaj o singur dat;
mesajul conine doar litere mici ale alfabetului englezesc.
Exemple
VENUS.IN
wvenusz
venus
VENUS.OUT
da
VENUS.IN
titanevmfh
titan
VENUS.OUT
venus
VENUS.IN
renunta
venus
VENUS.OUT
*
295
21.6.3. Parole
Descrierea problemei
Se consider un ir de caractere ASCII de lungime N, i mai multe iruri care
reprezint parole. O parl este valid dac i numai dac ea apare ca subsecven a
irului dat. Va trebui s determinai numrul parolelor valide.
Date de intrare
Prima linie a fiierului de intrare PAROLE.IN conine irul de caractere ASCII. Cea
de-a doua linie a fiierului va conine numrul K al parolelor care trebuie verificate.
Fiecare dintre urmtoarele K linii va conine cte o parol.
Date de ieire
Fiierul de ieire PAROLE.OUT va conine o singur linie pe care se va afla numrul
parolelor valide.
Restricii i precizri
1 K 1000;
1 N 500;
o parol va conine cel mult N caractere.
Exemplu
PAROLE.IN
AlphaBetaGamma
10
Alpha
Beta
Gamma
Delta
aBe
aGa
alpha
beta
gamma
delta
PAROLE.OUT
5
296
20.7.2. Venus
Pentru a vedea dac mesajul este autentic, va trebui doar s verificm apariia unui
subir ntr-un ir. Dac subirul apare, l vom elimina i apoi vom realiza decodificarea mesajului pe baza regulii descrise n enun.
Practic, nu va trebui s eliminm subirul, ci doar s memorm poziia la care ncepe acesta i s ignorm secvena corespunztoare n momentul n care realizm transformrile.
297
Analiza complexitii
Datele de intrare constau n dou iruri de caractere formate din N, respectiv M
elemente. Ca urmare, ordinul de complexitate al operaiei de citire a datelor este O(N
+ M).
Vom folosi un algoritm de potrivre a irurilor; dac utilizm algoritmul eficient
(KMP), ordinul de complexitate al operaiei este O(N + M).
Pentru a scrie datele de ieire va trebui doar s parcurgem irul, s verificm dac
poziia curent face parte din semntur i, dac nu, s scriem n fiierul de ieire
caracterul decodificat. Aceast operaie are ordinul de complexitate O(N).
n concluzie, ordinul de complexitate al algoritmului de rezolvare a acestei probleme este O(N + M) + O(N + M) + O(N) = O(N + M).
21.7.3. Parole
Problema se reduce la verificarea existenei mai multor subiruri ntr-un ir dat. Vom
lua n considerare fiecare subir i vom aplica un algoritm de potrivire a irurilor pentru a verifica dac subirul face sau nu parte din ir. Pe parcursul verificrilor vom
numra subirurile care fac parte din ir (parolele valide) i n final vom scrie acest
numr n fiierul de ieire.
Analiza complexitii
Datele de intrare constau ntr-un ir format din N caractere i alte K iruri de dimensiuni diferite. Dac notm prin S suma total a dimensiunilor celor K iruri, atunci ordinul de complexitate al operaiei de citire a datelor este O(N + S).
Vom aplica algoritmul KMP pentru fiecare dintre cele K iruri. Dac lungimea unui
subir este si, atunci pentru un subir vom avea ordinul de complexitate O(N + si).
Ordinul de complexitate al ntregii operaii de verificare are forma:
K
O(N + s ) = O( K N + S ) ,
i=1
deoarece avem:
K
s
i=1
=S.