10 Greedy Notes
10 Greedy Notes
1. Dacă se dores, te o solut, ie optimă, se caută o altă metodă de rezolvare decât greedy (folosind,
e.g., backtracking sau programare dinamică);
2. Dacă diferent, a dintre răspunsul optim s, i răspunsul produs de algoritmul greedy este tolera-
bilă ı̂n practică, se poate folosi algoritmul greedy (algoritmul produce o solut, ie aproximativă,
ı̂n acest caz se numes, te algoritm de aproximare).
1
1.4 Exemple de probleme care pot fi rezolvate prin strategii greedy
Algoritmii de tip greedy (lacom) sunt aplicat, i deseori ı̂n practică, inclusiv ı̂n viat, a de zi cu
zi. De exemplu, dacă plecat, i ı̂ntr-o excursie s, i vă pregătit, i bagajul, vet, i introduce ı̂ntâi ı̂n bagaj
lucrurile mari s, i apoi cele mici. Această strategie vă ajută să folosit, i spat, iul din bagaj ı̂n mod
eficient.
1.4.1 Bin-packing
Problemele computat, ionale ı̂n care la intrare se dau un container s, i o mult, ime de obiecte s, i la ies, ire
se cere o modalitate de a aranja obiectele ı̂n container se numesc probleme de tip bin-packing s, i
apar ı̂n diferite domenii.
De exemplu, ı̂n contextul jocurilor 2D, mai multe sprite-uri (imagini mici (e.g. 128x128 sau
64x64) sau serii de imagini mici reprezentând un personaj sau un alt element grafic din joc) trebuie
as, ezate fără să se suprapună ı̂ntr-un număr cât mai mic de imagini de dimensiuni mai mari (e.g.
1024x1024) care pot fi ı̂ncărcate de placa video ca texturi s, i apoi afis, ate pe ecran cât mai eficient.
Folosirea unui număr cât mai mic de texturi cres, te performant, a jocului s, i din acest motiv este de
dorit să “ı̂nghesuim” cât mai multe sprite-uri ı̂ntr-o singură textură. Cele mai multe framework-uri
pentru programarea jocurilor cont, in implementarea unor algoritmi pentru sprite-packing (căutat, i
“sprite packer” folosind un motor de căutare).
În cele mai multe cazuri, pentru problemele de tip bin-packing nu se cunoas, te o rezolvare
polinomială s, i din acest motiv se preferă un algoritm greedy care calculează o solut, ie aproximativă.
2
Scopul studentului este să participe la cât mai multe activităt, i (dar trebuie să participe la
fiecare de la ı̂nceput la sfârs, it s, i nu poate fi ı̂n două locuri ı̂n acelas, i timp). Ce activităt, i trebuie
să aleagă? În exemplul de mai sus, studentul poate participa la maxim 3 activităt, i: curs, teatru,
film sau codecamp, teatru, film.
Formal, problema select, iei activităt, ilor este următoarea:
Input: n - numărul de activităt, i
s[0..n − 1] - un tablou care cont, ine timpul de ı̂nceput al activităt, ilor
f [0..n − 1] - un tablou care cont, ine timpul de final al fiecărei activităt, i
a.ı̂. s[i] < f [i] pentru orice 0 ≤ i ≤ n − 1 s, i
f este ı̂n ordine crescătoare.
Output: A ⊆ {0, . . . , n − 1}
A este o mult, ime de activităt, i care nu se suprapun
A este de cardinal maxim.
Considerăm că activitatea i ı̂ncepe exact ı̂n momentul si s, i se termină put, in ı̂nainte de momen-
tul fi . Cu alte cuvinte, activitatea i durează de la si (inclusiv) până la fi (exclusiv). Astfel, două
activităt, i i, j se suprapun dacă [si , fi ) ∩ [sj , fj ) ̸= ∅ (remarcat, i faptul că intervalele sunt ı̂nchise la
stânga s, i deschise la dreapta).
Exerciţiul 2. Arătat, i că două activităt, i i, j nu se suprapun (sunt compatibile ı̂ntre ele) dacă s, i
numai dacă si ≥ tj sau sj ≥ ti .
De exemplu, pentru n = 5 s, i pentru tablourile s s, i f date mai jos:
i 0 1 2 3 4
s[i] 10 9 18 21 19
f [i] 12 17 20 22 24,
i 0 1 2
s[i] 9 15 17
f [i] 16 18 23,
strategia descrisă mai sus alege activitatea 1, care are durată de 3 ore. Dar activitatea 1 se
suprapune atât cu 0 cât s, i cu 2 s, i deci nu mai putem alege nicio altă activitate. Solut, ia {1} nu
este optimă, deoarece solut, ia {0, 2} cont, ine mai multe activităt, i.
IDEE 2.
În continuare, vom vedea o strategie greedy pentru problema select, iei activităt, ilor care conduce
ı̂n toate cazurile la solut, ia optimă.
Strategia pe care o vom folosi:
2. dintre activităt, ile care au rămas, alegem activitatea i care se termină cel mai devreme
(intuitiv, deoarece ı̂mi lasă timp mai mult pentru următoarele activităt, i);
3. adăugăm i la A;
4. s, tergem i s, i toate celelalte activităt, i care se suprapun cu i din lista de activităt, i disponibile;
3
În pseudocod, strategia de mai sus poate fi descrisă astfel:
Întrebare. Strategia de rezolvare IDEE 1 nu produce tot timpul solut, ia optimă. Cum pot
fi sigur ca strategia descrisă ı̂n IDEE 2 produce tot timpul solut, ia optimă? Răspuns. Putem
demonstra acest lucru.
În primul rând, vom arăta că, pentru orice mult, ime S de activităt, i, există o submult, ime S ′ de
activităt, i care:
• cont, ine doar activităt, i compatibile ı̂ntre ele (care nu se suprapun),
• este de cardinal maxim s, i
• cont, ine activitatea care se termină cel mai devreme din S.
Cu alte cuvinte, fără a pierde din generalitate, ı̂ntr-o mult, ime de cardinal maxim de activităt, i
compatibile ı̂ntre ele se poate alege activitatea care se termină cel mai devreme:
Lemă 1 (Lema de alegere lacomă). Fie S ⊆ {0, 1, . . . , n − 1} o mult, ime nevidă de activităt, i (nu
neapărat compatibile ı̂ntre ele).
Fie x activitatea din S care se termină cel mai devreme.
Există o submult, ime S ′ ⊆ S a mult, imii S care:
Proof. Fie S ′′ o submult, ime oarecare a lui S de activităt, i compatibile ı̂ntre ele de cardinal maxim.
Nu s, tim dacă x ∈ S ′′ .
Fie y activitatea din S ′′ care se termina cel mai devreme.
Alegem S ′ = (S ′′ \ {y}) ∪ {x}.
Observăm că:
Mai avem de arătat că S ′ cont, ine doar activităt, i compatibile ı̂ntre ele:
Cum y este activitatea care se termină cel mai devreme din S ′′ s, i cum S ′′ cont, ine doar activităt, i
compatibile ı̂ntre ele, rezultă că ∀z ∈ S ′′ \ {y}, f [y] ≤ s[z]. Dar y ∈ S ′′ , S ′′ ⊆ S s, i x ∈ S este
activitatea din S care se termină cel mai devreme. Deci x se termină ı̂naintea lui y: f [x] ≤ f [y].
Rezultă că ∀z ∈ S ′′ \ {y}, f [x] ≤ s[z], ceea ce ı̂nseamnă că x este compatibilă cu toate activităt, ile
din S ′′ \ {y}, deci S ′ cont, ine doar activităt, i compatibile ı̂ntre ele.
Am arătat că, fără a pierde optimalitatea, putem alege activitatea care se termină cel mai
devreme.
Pentru a arăta că algoritmul, ı̂n ı̂ntregimea sa, produce o solut, ie optimă, a mai rămas de arătat:
combinarea activităt, ii care se termină cel mai devreme cu restul activităt, ilor alese de algoritm este
o solut, ie optimă. Pentru a formaliza acest lucru, avem nevoie de not, iunea de subproblemă:
4
Definiţie 1. În contextul problemei select, iei activităt, ilor, o subproblemă este o submult, ime de
activităt, i.
Example 1. Pentru instant, a n = 5 s, i pentru tablourile s s, i f date mai jos:
i 0 1 2 3 4
s[i] 10 9 18 21 19
f [i] 12 17 20 22 24,
subproblemele sunt ı̂n număr de 25 = 32 s, i includ: ∅, {0, 2, 3, 4}, {1, 2, 3, 4}, {0, 2, 4}, {0, 1, 2, 3, 4}.
Lemă 2 (Proprietatea de substructură optimă). Fie S o subproblemă nevidă s, i x ∈ S activitatea
aleasă prin strategia greedy (cea care se termină cel mai devreme). Fie A ⊆ S o submult, ime de
activităt, i compabilite ı̂ntre ele de cardinal maxim care cont, ine x (x ∈ A – prin lema de alegere
greedy, această mult, ime A există).
Fie B = A \ {x}. Atunci B este o solut, ie optimă pentru S \ {z | z se suprapune peste x}.
Proof. Presupunem (prin reducere la absurd) că există o solut, ie C mai bună decât B pentru
subproblema S \ {x}. Atunci C ∪ {x} ar fi o solut, ie pentru S mai bună decât A, ceea ce contrazice
optimalitatea lui A.
Demonstrat, ia proprietăt, ii de substructură optimă este ı̂n general foarte simplă. În general,
proprietatea de substructură optimă indică faptul că subsolut, iile unei solut, ii optime sunt la rândul
lor solut, ii optime pentru subprobleme.
Prin induct, ie, folosindu-ne de cele două leme de mai sus, este us, or de demonstrat corectitudinea
algoritmului:
Teoremă 1. Strategia greedy de mai sus produce o solut, ie optimă.
Proof. Vom proceda prin induct, ie după mult, imea S de activităt, i disponibile.
Prin lema de alegere greedy, există o solut, ie optimă A pentru S astfel ı̂ncât x ∈ A. Prin ipoteza
de induct, ie, algoritmul găses, te o solut, ie optimă B pentru subproblema T = {i ∈ S | s[i] ≥ f [x]}
(T este strict inclusă ı̂n S). Prin lema de substructură optimă, {x} ∪ A este o solut, ie optimă (cea
găsită de algoritm).
O demonstrat, ie alternativă, care poate fi mai simplu de ı̂nt, eles fiindcă pasul inductiv este
explicitat:
Proof. Fie s1 , . . . , sk lista de activităt, i selectată de algoritmul greedy. Presupunând că nu e optimă,
căutăm cel mai mic număr j ∈ {1, 2, 3, . . .} astfel ı̂ncât să existe o listă optimă de activităt, i care
cont, ine primele j − 1 activităt, i din s1 , . . . , sn s, i apoi alte activităt, i:
s1 , . . . , sj−1 , tj , . . . , tm .(tj ̸= sj )
Presupunem că activităt, ile din solut, ia optimă s1 , . . . , sj−1 , tj , . . . , tm sunt ordonate crescător
(fiind compatibile ı̂ntre ele, nu contează dacă după timpul de ı̂nceput sau după cel de sfârs, it –
obt, inem aceeas, i ordine).
Prin definit, ie, sj este compatibilă cu s1 , . . . , sj−1 s, i ı̂ncepe mai devreme decât tj . Deci
s1 , . . . , sj−1 , sj , tj+1 , . . . , tm ar fi s, i ea o solut, ie optimă, contrazicând minimalitatea lui j.
1. Algoritmii greedy = secvent, ă de alegeri locale, alegeri care par a fi cele mai bune ı̂n momentul
respectiv;
5
2. Odată făcută o alegere, nu ne putem răzgândi.
3. Câteodată această solut, ie conduce la un optim global (e.g. problema select, iei activităt, ilor);
alteori nu (e.g. problema discretă a rucsacului).
i 0 1 2
w[i] 1 2 3
v[i] 10 15 20
Rucsacul are capacitate de W = 5 kg.
O solut, ie optimă pentru varianta continuă:
1. iau 100% din primul obiect (deci p[0] = 1). Câs, tig: 1 × 10 = 10, capacitate rămasă: 5 − 1 = 4
kg.
2. iau 100% din al doilea obiect (deci p[1] = 1). Câs, tig: 10 + 1 × 15 = 25, capacitate rămasă:
4 − 2 = 2 kg.
3. iau 2/3 din al treilea obiect (deci p[2] = 0.66 . . .). Câs, tig: 25 + 2/3 × 20 = 38.33 . . ..
O abordare greedy care conduce la solut, ia optimă este să alegem cât mai mult din obiectul cu
câs, tig unitar (câs, tig / kilogram) cel mai mare.
Exerciţiul 3. Identificat, i subproblemele pentru problema rucsacului - varianta continuă.
Enunt, at, i s, i demonstrat, i lema de alegere greedy.
Enunt, at, i proprietatea de substructură optimă (s, i demonstrat, i-o, dar demonstrat, ia va fi sur-
prinzător de simplă).
6
Problema rucsacului - varianta discretă
Un hot, a spart un magazin s, i a găsit n bunuri. Al i-lea bun valorează vi lei s, i cântăres, te wi
kilograme. Hot, ul are un rucsac care poate să ducă cel mult W kilograme de bunuri. Niciun
bun nu poate fi sect, ionat - obiectul i trebuie furat integral sau deloc. Hot, ul vrea să
maximizeze valorea obiectelor pe care le va pune ı̂n rucsac.
i 0 1 2
w[i] 1 2 3
v[i] 10 15 20
Rucsacul are capacitate de W = 5 kg.
O solut, ie optimă pentru varianta discretă:
Abordările greedy nu produc solut, ii optime pentru varianta discretă (vezi capitolele următoare:
programare dinamică, backtracking).
Coduri prefix
Orice astfel de cod se poate reprezenta ı̂n mod unic printr-un arbore binar cu n frunze:
7
0 1
a
0 1
b
0 1
c d
Formalizarea problemei
Input: n - numărul de caractere distincte; c[0..n − 1] - numărul de aparit, ii ale fiecărui caracter.
Output: un arbore binar care reprezintă codul prefix optim.
Exemplu: dacă n = 4 s, i c = [45, 30, 15, 10], atunci arborele precedent este un răspuns corect
(a = 1, b = 01, c = 000, d = 001).
Ideea: combină caracterele cu frecvent, ele cele mai reduse (pe tablă).
1. Q = ∅ (coadă cu prioritate)
2. for i = 0 to n − 1
[Link](info : i, frec : c[i], left : null, right : null)
3. for i = 0 to n − 2
x = new()
[Link] o = −1
[Link] = [Link]()
[Link] = [Link]()
[Link] = [Link] + [Link]
[Link](x)
4. return [Link]()
1. (Proprietatea de alegere greedy) Există un cod optim ı̂n care ultimele două caractere dpdv
al frecvent, ei au aceeas, i lungime s, i diferă doar ı̂n ultimul bit.
2. (Proprietatea de substructură optimă) Fie x, y cele două caractere cu frecvent, a cea mai mică.
Fie z un nou caracter astfel ı̂ncât c[z] = c[x] + c[y]. Fie T arborele binar care determină
codul optim pentru Σ \ {x, y} ∪ {z} s, i T ′ arborele binar obt, inut din T prin ı̂nlocuirea lui z
cu un nou nod având copiii x s, i y. Atunci T ′ este optim pentru Σ.
3. Timp de rulare: O(nlogn), dacă coada cu prioritate este implementată printr-un heap binar.
8
1.4.7 Matroizi
Matroid
Mult, i algoritmi de tip greedy pot fi demonstrat, i folosind teoria matroizilor.
Definiţie 2. Un matroid este o pereche M = (S, I) cu proprietăt, ile:
dacă B ∈ I s, i A ⊆ B, atunci A ∈ I.
Matroid - exemplu
Fie G = (V, E) un graf s, i MG = (SG , IG ) definit astfel:
1. SG = E, muchiile grafului
2. A ⊆ E ∈ I ddacă A nu cont, ine ciclu.
Matroid ponderat
Fie M = (S, I).
Fie w : S → N o funct, ie care asociază fiecărui element x din S o pondere w(x).
Funct, ia w se extinde la mult, imi A ⊆ S astfel: w(A) = Σx∈A w(x).
Teoremă 2. Dacă M este matroid, atunci există un algoritm greedy pentru găsirea unei mult, imi
independente de pondere maximă.
• if A ∪ {x} ∈ I
A = A ∪ {x}
9
Lemă 4 (Proprietatea de substructură optimă). Fie x primul element ales de algoritm pentru
matroidul M = (S, I).
Fie matroidul M ′ = (S ′ , I ′ ), definit astfel:
• S ′ = {y ∈ S | {x, y} ∈ I};
• I ′ = {B ⊆ S \ {x} | B ∪ {x} ∈ I}.
Fie A solut, ia optimă găsită de algoritm pentru matroidul M (x ∈ A). Atunci A \ {x} este
solut, ie optimă pentru M ′ .
10
1 2 1 2
20
20 30
50
30
3 4 3 4
40
10
5 5
10
Studii de caz Arborele parţial de cost minim
10
1 2 1 2
20
20 30
50
30
3 4 3 4
40
10
5 5
Studii de caz Arborele parţial de cost minim
10 10
1 2 1 2
20
20 30
50
30
3 4 3 4
40
10
5 5
Algoritmul luiAlgoritmul
Kruskal lui
UAIC) Kruskal
D. Lucanu (FII- - pasul 3 Algoritmi greedy PA 2014/2015 38 / 42
10 10
1 2 1 2
20
20 30
50
30
3 4 3 4
40
10 10
5 5
11
Studii de caz Arborele parţial de cost minim
10 10
1 2 1 2
20 20
20 30
50
30
3 4 3 4
40
10 10
5 5
Studii de caz Arborele parţial de cost minim
10 10
1 2 1 2
20 20
20 30 30
50
30
3 4 3 4
40
10 10
5 5
1. SG = E, muchiile grafului
Dacă definim w(e) = M − l(e) (unde M este un număr suficient de mare), atunci algoritmul
lui Kruskal este o instant, ă a algoritmului general pentru matroizi.
Concluzii
12
3. Multe probleme de optimizare au solut, ii optime ce pot fi găsite cu greedy (e.g. problema
continuă a rucsacului). Pentru alte probleme (e.g. problema discretă a rucsacului), algoritmii
greedy nu produc solut, ia optimă.
4. Matroidul este structură matematică cu ajutorul căreia putem modela diverse probleme de
optimizare. Dacă problema se poate modela cu ajutorul unui matroid (ponderat), atunci
algoritmul greedy produce solut, ia optimă. Avantajul este că nu mai avem de demonstrat
algoritmul, deoarece am arătat deja că este corect pentru orice matroid. Este suficient să
arătăm că putem modela problema ca un matroid.
1 Exercit, ii seminar
1.1 Problema select, iei activităt, ilor
1. Arătat, i că strategiile greedy care urmează nu conduc ı̂ntotdeauna la solut, ia optimă:
• selectează activitatea cea mai scurtă (care nu se suprapune cu activităt, ile deja alese);
soluţie ▶pentru activităţile: [1,5), [4,7), [6,10) se alege cea mai scurtă [4,7) şi ulterior nu se mai
poate adăuga nicio activitate. Soluţia optimă e [1,5), [6,10).◀
• selectează activitatea care se suprapune cu cât mai put, ine alte activităt, i (s, i care nu
se suprapune cu activităt, ile deja alese). soluţie ▶11 activitaţi: ı̂n soluţia optimă sunt 4
activităţi: [1,7) [9,15), [17, 22), [24,29). Singura activitate care se suprapune cu doar alte două
activitaţi este [12, 18). Două grupuri a câte trei activităţi identice cresc numărul de suprapuneri
peste cele 4 din soluţia optimă, astfel ele nu vor fi alese ı̂n prima etapă şi nici nu vor putea fi alese
ulterior din cauza suprapunerii cu [12,18). Din cele două grupuri de câte trei putem selecta doar
câte una. Activitatea [- -x- -) incepe la pozitia caracterului [, se termina la ) si se suprapune cu x
alte activitati.◀
00000000011111111112222222222 c i f r a z e c i l o r
12345678901234567890123456789 c i f r a u n i t a t i l o r a l e c a p e t e l o r
[−−3−−) [−−4−−) [−−4−) [−−3−)
[−−4−−) [−−2−−) [−−4−−)
[−−4−−) [−−4−−)
[−−4−−) [−−4−−)
1.2 Problema plăt, ii unei sume cu număr cât mai mic de bancnote
1. Imaginat, i-vă că trăit, i ı̂ntr-o t, ară ı̂n care sunt disponibile bancnote de 1 leu, de 7 lei s, i de 8
lei. Dat, i exemplu de o sumă de bani pentru care strategia greedy descrisă ı̂n notele de curs
nu produce solut, ia optimă.
soluţie ▶Pentru suma 14 de exemplu, algoritmul greedy alege prima monedă de valoare 8, şi este nevoit
ulterior să mai folosească aloce ı̂ncă 6 bancnote de valoare 1, ajungând la 7 bancnote ı̂n total. Optim e
7 + 7 = 14 deci două bancnote.◀
(ı̂n continuare presupunem că avem la dispozit, ie bancnotele standard)
2. Scriet, i ı̂n Alk algoritmul greedy pentru plata unei sume de bani folosind număr minim de
bancnote.
3. Identificat, i subproblemele pe care le rezolvă algoritmul greedy.
4. Demonstrat, i proprietatea de alegere greedy: Fie b valoarea celei mai mari bancnote care este
mai mică decât suma s de achitat. Atunci există o solut, ie optimă de a plăti s care ı̂ncepe
cu b.
13
5. Enunt, at, i s, i demonstrat, i proprietatea de substructură optimă (demonstrat, ia ı̂n sine este
foarte us, oară).
1.3 Matroizi
1. Fie M = (S, I) un matroid. Arătat, i că ∅ ∈ I.
2. Fie M = (S, I) un matroid. Arătat, i că orice mult, ime maximală (dpdv al incluziunii) din I
are acelas, i cardinal.
3. Arătat, i că matroidul MG asociat grafului G (definit ı̂n notele de curs) este ı̂ntr-adevăr
matroid.
2 Exercit, ii suplimentare
1. Demonstrat, i că algoritmul greedy produce solut, ia optimă dacă bancnotele disponibile sunt
puteri ale unui număr (e.g. 1, 2, 4, 8, . . .).
2. Arătat, i că problema select, iei activităt, ilor ı̂n care vectorul f este ordonat s, i problema select, iei
activităt, ilor ı̂n care vectorul f nu este neapărat ordonat se reduc una la cealaltă (formalizat, i-
le ı̂ntâi ca pereche input-output).
3. Găsit, i ı̂ncă o strategie greedy pentru problema select, iei activităt, ilor care să conducă la solut, ia
optimă.
4. Găsit, i un algoritm care primes, te n puncte x1 , . . . , xn de pe dreapta Ox s, i găses, te numărul
minim de intervale-unitate ([a, b] este interval-unitate dacă b = a + 1) care acoperă toate
punctele.
5. Găsit, i codul Huffman corespunzător următoarelor frecvent, e: 1, 1, 2, 3, 5, 8, etc.
soluţie ▶Considerând caracterele a, b, c, d, e, f cu frecvenţele 1, 1, 2, 3, 5 şi respectiv 8, codurile
asociate caracterelor vor fi: f − 0, e − 10, d − 110, c − 1111, b − 11101, a − 11100.
referinţe calculator, generator arbore, algoritm şi descriere◀
6. Arătat, i că (S, Ik ) este matroid, dacă S este o mult, ime finită s, i Ik este mult, imea tuturor
submult, imilor lui S de cardinal ≤ k.
7. Căutat, i algoritmul lui Prim ı̂n literatură s, i arătat, i că produce solut, ia optimă. Poate fi
exprimat cu ajutorul matroizilor?
8. Fie S un şir de caractere definit peste alfabetul binar {0, 1}. Peste acest şir se poate aplica
următoarea operaţie: se alege o poziţie Si astfel ı̂ncât Si = 1 şi se atribuie elementului
respectiv valoarea 0. Care este numărul minim de operaţii ce trebuie aplicate lui S astfel ı̂ncât
şirul să nu conţină cuvântul 101 ca substring (factor). De exemplu, pentru S = 1101101010,
numărul minim de operaţii este 2, o posibilitate fiind aplicarea operaţiei peste pozitiile
subliniate: 1101101010 ⇒ 1001100010. Descrieţi un algoritm greedy de complexitate liniară
şi argulentaţi corectitudinea algoritmului.
soluţie ▶Se parcurge şirul de la stânga la dreapta, atunci când ı̂ntâlnim o valoare Si = 1 precedată de
10, formându-se astfel un 10 + 1 = 101, se aplica operaţia peste Si . Deoarece prefixul până la poziţia
i − 1 este deja rezolvat, liber de 101, nu are sens să aplicăm operaţia peste Si−2 , iar poziţia i e prefrabilă
pentru că poate elimina o eventuală apariţie 101 ulterioară, dacă următoatele caractere de la poziţiile i
şi i + 1 sunt 01. sursă, tutorial - ı̂n partea dreapta a paginii, la Contest materials.◀
14