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.