Boyer-Moore-algoritmus
Kiejtés
- IPA: [ ˈboiɛrmoorɛɒlɡoritmuʃ]
Főnév
- (matematika) A Boyer-Moore-algoritmus egy hatékony szövegkeresési algoritmus, amely egy minta (pattern) egy adott szövegben (text) való első előfordulását keresi. Az algoritmus hatékonysága a jobb-minta összehasonlításokon és két előfeldolgozási lépésen alapul: a Bad Character és a Good Suffix heurisztikákon. Az algoritmus jellemzően (O(n))-es futási időt ér el a gyakorlatban, ahol (n) a szöveg hossza.
Fő ötlet
- Jobbról balra történő mintaillesztés:
- Az algoritmus a mintát a szöveg adott pozíciójához illeszti jobbról balra haladva.
- Előfeldolgozási lépések:
- Bad Character heurisztika: Ha egy karakter nem illeszkedik, az algoritmus kihasználja annak pozícióját a mintában.
- Good Suffix heurisztika: Ha egy részleges egyezés nem folytatható, a már illeszkedett szuffixumot használja a minta gyors eltolásához.
- Gyors eltolás:
- A mintát a lehető legnagyobb mértékben eltolja, elkerülve a felesleges összehasonlításokat.
Algoritmus működése
1. Előfeldolgozás
- Bad Character táblázat:
- Létrehoz egy táblázatot, amely minden karakterhez tárolja a minta utolsó előfordulási helyét. Ha egy karakter nincs a mintában, akkor -1-et tárol.
- Ha a minta adott karaktere nem illeszkedik a szöveghez, az algoritmus a táblázat alapján eltolja a mintát.
- Good Suffix táblázat:
- Ha a minta részben illeszkedik, de nem teljesen, az algoritmus ezt az információt használja a minta optimális eltolására.
2. Mintaillesztés
- A mintát a szöveg elejéhez igazítjuk.
- Jobbról balra haladva összehasonlítjuk a minta karaktereit a szöveggel.
- Ha eltérést találunk, a Bad Character és a Good Suffix heurisztikák közül a nagyobb eltolást választjuk.
3. Ismétlés
- Az algoritmus ismétli az eltolást és az összehasonlítást, amíg a minta végig nem ér a szövegen.
Pszeudokód
BoyerMoore(text, pattern): n = len(text) m = len(pattern) # Előfeldolgozás bad_char = create_bad_char_table(pattern) good_suffix = create_good_suffix_table(pattern) i = 0 while i <= n - m: j = m - 1 while j >= 0 and pattern[j] == text[i + j]: j -= 1 if j < 0: print(f"Minta megtalálva itt: {i}") i += good_suffix[0] else: shift = max(1, j - bad_char[text[i + j]]) i += shift
Előfeldolgozás részletei
1. Bad Character táblázat
def create_bad_char_table(pattern):
bad_char = [-1] * 256 # ASCII karakterek
for i in range(len(pattern)):
bad_char[ord(pattern[i])] = i
return bad_char
2. Good Suffix táblázat
def create_good_suffix_table(pattern):
m = len(pattern)
good_suffix = [0] * m
border = [0] * (m + 1)
j = m
for i in range(m - 1, -1, -1):
if pattern[i:] == pattern[m - j:]:
border[j] = i + 1
j -= 1
j = 0
for i in range(m):
if border[j] == 0:
good_suffix[i] = m - j
else:
good_suffix[i] = m - border[j]
j += 1
return good_suffix
Python implementáció
def boyer_moore(text, pattern):
n = len(text)
m = len(pattern)
if m == 0:
return []
# Előfeldolgozás
bad_char = create_bad_char_table(pattern)
good_suffix = create_good_suffix_table(pattern)
i = 0
results = []
while i <= n - m:
j = m - 1
while j >= 0 and pattern[j] == text[i + j]:
j -= 1
if j < 0:
results.append(i)
i += good_suffix[0]
else:
i += max(1, j - bad_char[ord(text[i + j])])
return results
# Példa
text = "ABAAABCDABC"
pattern = "ABC"
result = boyer_moore(text, pattern)
print("A minta megtalálható pozíciói:", result)
Kimenet:
A minta megtalálható pozíciói: [4, 8]
C++ implementáció
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
vector<int> create_bad_char_table(const string& pattern) {
vector<int> bad_char(256, -1); // ASCII karakterek
for (int i = 0; i < pattern.size(); ++i) {
bad_char[pattern[i]] = i;
}
return bad_char;
}
vector<int> boyer_moore(const string& text, const string& pattern) {
int n = text.size();
int m = pattern.size();
vector<int> result;
if (m == 0) return result;
vector<int> bad_char = create_bad_char_table(pattern);
int shift = 0;
while (shift <= n - m) {
int j = m - 1;
while (j >= 0 && pattern[j] == text[shift + j]) {
--j;
}
if (j < 0) {
result.push_back(shift);
shift += (shift + m < n) ? m - bad_char[text[shift + m]] : 1;
} else {
shift += max(1, j - bad_char[text[shift + j]]);
}
}
return result;
}
int main() {
string text = "ABAAABCDABC";
string pattern = "ABC";
vector<int> positions = boyer_moore(text, pattern);
cout << "A minta megtalálható pozíciói: ";
for (int pos : positions) {
cout << pos << " ";
}
cout << endl;
return 0;
}
Kimenet:
A minta megtalálható pozíciói: 4 8
Előnyök
- Hatékonyság:
- Gyakorlati helyzetekben (O(n))-es teljesítmény érhető el.
- Optimális működés:
- Kiváló teljesítményt nyújt hosszú szövegek és minták esetén.
- Heurisztikák kombinációja:
- A két heurisztika hatékony eltolásokat tesz lehetővé.
Hátrányok
- Előfeldolgozás költsége:
- Az előfeldolgozás időigényes lehet.
- Kis minták:
- Rövid minták esetén más algoritmusok (pl. Knuth-Morris-Pratt) hatékonyabbak lehetnek.
Összegzés
A Boyer-Moore-algoritmus az egyik leggyorsabb szövegkeresési algoritmus, amelyet különösen nagy szövegek és minták keresésére használnak. A Bad Character és a Good Suffix heurisztikák kombinációja révén az algoritmus hatékonyan csökkenti az összehasonlítások számát, így a gyakorlatban nagyon gyors. Ezért az algoritmus népszerű választás, ha nagy adathalmazokban kell keresni mintákat.
- Boyer-Moore-algoritmus - Értelmező szótár (MEK)
- Boyer-Moore-algoritmus - Etimológiai szótár (UMIL)
- Boyer-Moore-algoritmus - Szótár.net (hu-hu)
- Boyer-Moore-algoritmus - DeepL (hu-de)
- Boyer-Moore-algoritmus - Яндекс (hu-ru)
- Boyer-Moore-algoritmus - Google (hu-en)
- Boyer-Moore-algoritmus - Helyesírási szótár (MTA)
- Boyer-Moore-algoritmus - Wikidata
- Boyer-Moore-algoritmus - Wikipédia (magyar)