Sunteți pe pagina 1din 2

Rotatie minim lexicografic – NlogN

Precizam intai ca atat o solutie O(N*lg2 N) cat si una O(N*lg N) pot fi obtinute folosind structura de
date "siruri de sufixe" (1). Din pacate aceste solutii nu sunt foarte usor de implementat, iar constanta
din notatia O este destul de mare cat sa merite cautarea unei solutii alternative. Vom prezenta in
continuare o solutie de complexitate O(N*lg N), mult mai usor de implementat odata ce este inteleasa.
Primul pas pentru obtinerea acestei solutii este folosirea unei strategii de tip "turneu", si anume la
fiecare iteratie se pastreaza o lista cu rotatiile care ar putea fi minime. Initial lista va avea toate cele N
rotatii, iar de fiecare data se iau rotatiile doua cate doua din lista si se elimina cea mai mare dintre cele
doua din punct de vedere lexicografic. Procesul se reia pana cand se obtine o lista cu un singur element,
reprezentand rotatia minima. Cum la fiecare pas numarul de elemente din lista se injumateste, este usor
de vazut ca procesul nu se va repeta de mai mult de [log 2 N] ori. Desi la prima vedere acest algoritm
are timpul de rulare O(N2*lg N), vom arata in continuare ca sunt suficiente O(N) comparatii de
caractere per total la fiecare repetare:
Fie R i si R j doua rotatii (presupunem fara a restrange generalitatea ca i < j) aflate pe pozitii
consecutive in lista, care urmeaza sa fie comparate, una din fiind aleasa pentru eliminare. Vom
demonstra in continuare ca este suficienta compararea acestor rotatii folosindu-ne doar de primele j - i
caractere.

2j-i-
i ... j-1 j ... 2j-i ... 0 ... i-1
1
A = i...j-1
B = j...2j-i-1
C = 2j-i...i-1 (indicii sunt considerati modulo N )
Fie sirul R i impartit in trei bucati A, B, C, ca in figura de mai sus. Conform figurii, R i = ABC, iar R j =
BCA, bucatile A si B avand fiecare j-i caractere. Comparand doar primele j-i caractere, vom compara
bucatile A si B, astfel:
 A < B -> R i < R j -> se elimina R j
 A > B -> R i > R j -> se elimina R i
 A = B -> se elimina R j ( se presupune ca R i < R j )

Este evident ca in primele doua cazuri decizia de eliminare este corecta. Daca A = B , iar decizia luata
de eliminare a fost gresita, anume R i > R j, cum R i = ABC = AAC si R j = BCA = ACA, inseamna ca
A > C (daca A ar fi fost egal cu C atunci R i = R j, si nu ar mai fi contat ce element se elimina), deci
elementul pastrat va fi oricum eliminat de rotatia R 2j-i = CAA sau de o alta rotatie care s-a dovedit a fi
mai mica decat CAA la pasii anteriori. La a i-a parcurgere a listei, distanta intre doua rotatii aflate pe
pozitii consecutive in lista este maxim 2i-1, iar in lista sunt cel mult [ n / 2i-1 ] elemente, astfel facandu-
se O(N) comparatii. In acest mod obtinem un algoritm corect de complexitate O(N * log N).

L <- {0,1,2,...,N-1};
cat timp |L|>1 executa
pentru k <- 1, |L|-1, +2 executa
i <- L[k]; j <- L[k+1];
A <- S[i..j-1]; B <- S[j..2j-i-1];
daca A <= B atunci elimina L[k+1];
altfel elimina L[k];
sfarsit pentru
sfarsit cat timp
scrie L[1]
Spre exemplu, pentru sirul S = ("m", "i", "s", "s", "i", "s", "s", "i", "p", "p", "i") lista va contine initial
elementele {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
La primul pas se efectueaza (caracterele ingrosate sunt cele ce se vor compara):
R0 = mississippi > R1 = ississippim
R2 = ssissippimi = R3 = sissippimis
R4 = issippimiss < R5 = ssippimissi
R6 = sippimissis > R7 = ippimississ
R8 = ppimississi = R9 = pimississip
Lista va fi acum {1, 2, 4, 7, 8, 10}
Pasii urmatori sunt:
R1 = ississippim < R2 = ssissippimi
R4 = issippimiss > R7 = ippimississ
R8 = ppimississi > R10 = imississipp
L = {1, 7, 10}
R1 = ississippim > R7 = ippimississ
L = {7, 10}
R7 = ippimississ > R10 = imississipp
L = {10}

S-ar putea să vă placă și