|
Grafy a tabuľky |
Boyer-Mooreov algoritmus
|
Priemerné počty porovnaní vybraných implementácií |
//Boyer-Mooreov algoritmus vyhladavania zadaneho vzoru "vzor" s poctom znakov "dlzka_v"
//v retazci "retazec" s poctom znakov "dlzka_r"
//funkcia vracia index prveho znaku najdeneho vzoru v retazci
//(v pripade neuspechu vyhladavania vracia -1)
int CRetazec::najdi_BM(char *vzor, int dlzka) {
int postupnost[MAX_DLZKA_VZORU];
int vyskyt[MAX_VELKOST_ABECEDY];
pre_postupnost(vzor, dlzka, postupnost);
pre_vyskyt(vzor, dlzka, vyskyt);
int j = 0;
while ( ++p_a_porovnani_ && j <= velkost() - dlzka) {
for (int i = dlzka - 1; ++p_b_porovnani_ && i >= 0 &&
++p_b_porovnani_ && vzor[i] == retazec_[i + j]; i--);
if ( ++p_b_porovnani_ && i < 0) {
return j;
//j += postupnost[0];
}
else {
++p_c_porovnani_;
if (postupnost[i] >= vyskyt[retazec_[i + j]] - dlzka + 1 + i)
j+=postupnost[i];
else j+=vyskyt[retazec_[i + j]] - dlzka + 1 + i;
}
}
return -1;
}
//funkcia na vytvorenie pomocneho pola pre BM algoritmus
void CRetazec::pre_postupnost(char *vzor, int dlzka, int postupnost[]) {
int suff[MAX_DLZKA_VZORU];
suffixes(vzor, dlzka, suff);
for (int i = 0; ++p_d_porovnani_ && i < dlzka; i++) postupnost[i] = dlzka;
int j = 0;
for (i = dlzka - 1; ++p_d_porovnani_ && i >= -1; i--)
if ((++p_d_porovnani_ && i == -1) || (++p_d_porovnani_ && suff[i] == i + 1))
for (; ++p_d_porovnani_ && j < dlzka - 1 - i; j++)
if (++p_d_porovnani_ && postupnost[j] == dlzka)
postupnost[j] = dlzka - 1 - i;
for (i = 0; ++p_d_porovnani_ && i <= dlzka - 2; i++)
postupnost[dlzka - 1 - suff[i]] = dlzka - 1 - i;
}
//funkcia na vytvorenie pomocneho pola pre BM algoritmus
//(pre funkciu, ktora vytvara pomocne pole pre BM algoritmus)
void CRetazec::suffixes(char *vzor, int dlzka, int *suff) {
int f;
suff[dlzka - 1] = dlzka;
int g = dlzka - 1;
for (int i =dlzka - 2; ++p_d_porovnani_ && i >= 0; --i) {
if ( ++p_d_porovnani_ && i > g &&
++p_d_porovnani_ && suff[i + dlzka - 1 - f] < i - g)
suff[i] = suff[i + dlzka - 1 - f];
else {
if (++p_d_porovnani_ && i < g) g = i;
f = i;
while ( ++p_d_porovnani_ && g >= 0 &&
++p_d_porovnani_ && vzor[g] == vzor[g + dlzka - 1 - f])
g--;
suff[i] = f - g;
}
}
}
//funkcia na vytvorenie pomocneho pola pre BM algoritmus
void CRetazec::pre_vyskyt(char *vzor, int dlzka, int vyskyt[]) {
for (int i = 0; ++p_d_porovnani_ && i < MAX_VELKOST_ABECEDY; i++)
vyskyt[i] = dlzka;
for (i = 0; ++p_d_porovnani_ && i < dlzka - 1; i++)
vyskyt[vzor[i]] = dlzka - i - 1;
} |
Počet porovnaní, cyklov a času trvania algoritmu pre veľkosť abecedy=3 znaky, veľkosť vzoru=3 znaky. |
počet znakov v prehľadávanom reťazci |
p_a_porovnani_ |
p_b_porovnani_ |
p_c_porovnani_ |
p_d_porovnani_ |
čas |
10 |
6,000 |
19,00 |
5,000 |
297,0 |
2,453 |
100 |
56,00 |
206,0 |
52,00 |
297,0 |
4,387 |
1.000 |
503,0 |
2074,0 |
464,0 |
297,0 |
23,02 |
10.000 |
4992,0 |
20612,0 |
4636,0 |
297,0 |
208,5 |
100.000 |
50125,0 |
205993,0 |
46511,0 |
297,0 |
2079,0 |
|
Počet porovnaní je opäť závislý od veľkosti prehľadávaného reťazca. Súceť a, b, c porovnaní je približne 3*n. d porovnania súvisia s vytváraním pomocných tabuliek a ich počet je vzhľadom na meniacu sa veľkosť prehľadávaného reťazca konštantný. |
|
Počet porovnaní, cyklov a času trvania algoritmu pre veľkosť abecedy=24 znakov, veľkosť vzoru=3 znaky. |
počet znakov v prehľadávanom reťazci |
p_a_porovnani_ |
p_b_porovnani_ |
p_c_porovnani_ |
p_d_porovnani_ |
čas |
10 |
4,000 |
9,000 |
3,000 |
297,0 |
2,393 |
100 |
36,00 |
107,0 |
35,00 |
297,0 |
3,407 |
1.000 |
353,0 |
1090,0 |
352,0 |
297,0 |
13,55 |
10.000 |
3488,0 |
10746,0 |
3486,0 |
297,0 |
113,0 |
100.000 |
34783,0 |
107553,0 |
34775,0 |
297,0 |
1127,0 |
|
Počet porovnaní je opäť závislý od veľkosti prehľadávaného reťazca. Súceť a, b, c porovnaní je vždy menší ako 1,8*n. d porovnania súvisia s vytváraním pomocných tabuliek a ich počet je vzhľadom na meniacu sa veľkosť prehľadávaného reťazca konštantný. |
|
Počet porovnaní, cyklov a času trvania algoritmu pre veľkosť abecedy=3 znaky, veľkosť vzoru=9 znakov. |
počet znakov v prehľadávanom reťazci |
p_a_porovnani_ |
p_b_porovnani_ |
p_c_porovnani_ |
p_d_porovnani_ |
čas |
10 |
2,000 |
9,000 |
1,000 |
379,0 |
2,757 |
100 |
27,00 |
120,0 |
26,00 |
379,0 |
3,751 |
1.000 |
324,0 |
1362,0 |
322,0 |
379,0 |
17,10 |
10.000 |
3153,0 |
13237,0 |
3151,0 |
379,0 |
141,4 |
100.000 |
31613,0 |
133154,0 |
31606,0 |
379,0 |
1407,0 |
|
Počet porovnaní je opäť závislý od veľkosti prehľadávaného reťazca. Súceť a, b, c porovnaní sa pohybuje približne okolo hodnoty 2*n. d porovnania súvisia s vytváraním pomocných tabuliek a ich počet je vzhľadom na meniacu sa veľkosť prehľadávaného reťazca konštantný. |
|
Počet porovnaní, cyklov a času trvania algoritmu pre veľkosť abecedy=24 znakov, veľkosť vzoru=9 znakov. |
počet znakov v prehľadávanom reťazci |
p_a_porovnani_ |
p_b_porovnani_ |
p_c_porovnani_ |
p_d_porovnani_ |
čas |
10 |
2,000 |
3,000 |
1,000 |
379,0 |
2,729 |
100 |
12,00 |
33,00 |
11,00 |
379,0 |
3,051 |
1.000 |
123,0 |
374,0 |
122,0 |
379,0 |
6,609 |
10.000 |
1192,0 |
3691,0 |
1191,0 |
379,0 |
41,05 |
100.000 |
11900,0 |
36701,0 |
11899,0 |
379,0 |
398,5 |
|
Počet porovnaní je opäť závislý od veľkosti prehľadávaného reťazca. Súceť a, b, c porovnaní sa pohybuje približne okolo hodnoty 0,6*n. d porovnania súvisia s vytváraním pomocných tabuliek a ich počet je vzhľadom na meniacu sa veľkosť prehľadávaného reťazca konštantný. |
|
|
Závislost dĺžky času trvania algoritmu od veľkosti vstupného pola |
Pre abecedy s veľkým počtom znakov a dlhé vzory hľadané v prehľadávanom reťazci je efektivita tohto algoritmu najväčšia. Závislosť času prehľadávania od veľkosti prehľadávaného vzoru je lineárna. Na vyhľadávanie v malých poliach má však kritický dopad potrebná predpríprava a tá trvá dlhšie ako samotné vyhľadávanie v reťazci s dĺžkou 200 znakov algoritmom brute force. |
 |
|
10 |
100 |
1.000 |
10.000 |
100.000 |
veľkosť abecedy=3 znaky, dĺžka vzoru=3 znaky |
2,453 |
4,387 |
23,02 |
208,5 |
2079,0 |
veľkosť abecedy=24 znakov, dĺžka vzoru=3 znaky |
2,393 |
3,407 |
13,55 |
113,0 |
1127,0 |
veľkosť abecedy=3 znaky, dĺžka vzoru=9 znaky |
2,757 |
3,751 |
17,10 |
141,4 |
1407,0 |
veľkosť abecedy=24 znakov, dĺžka vzoru=9 znakov |
2,729 |
3,051 |
6,610 |
41,10 |
398,5 |
|
|
|
Poznámka: Algoritmy boli testované na počítači s procesorom AMD Athlon(tm) XP 1700+ a s 256 MB operačnou pamäťou pod operačným systémom Windows XP. Všetky časy uvedené v tabuľke sú v mikrosekundách. |