Rabin-Karp algoritmus
Kiejtés
- IPA: [ ˈrɒbiŋkɒrpɒlɡoritmuʃ]
Főnév
- (matematika, algoritmusok) A Rabin-Karp-algoritmus egy hatékony szövegkeresési algoritmus, amelyet Richard M. Karp és Michael O. Rabin dolgozott ki 1987-ben. Az algoritmus a karakterláncok hash értékein alapul, és egy vagy több minta gyors keresésére használható egy nagyobb szövegben.
Jellemzők
- Hashing:
- Az algoritmus hash függvényeket használ a szövegrészletek gyors összehasonlítására.
- Az összehasonlítás akkor történik karakterenként, ha a hash értékek megegyeznek.
- Alkalmazások:
- Szövegkeresés nagy szövegekben.
- DNS-szekvenciák összehasonlítása.
- Plágiumkeresés.
- Időkomplexitás:
- Legjobb eset: (O(n + m)), ahol (n) a szöveg hossza, (m) a minta hossza.
- Legrosszabb eset: (O(n m)), ha sok hash ütközés van.
Algoritmus működése
- Hash érték számítása:
- Számítsuk ki a minta ((P)) és a szöveg első részletének ((T_1)) hash értékét egy (h) hash függvénnyel.
- Csúszóablakos ellenőrzés:
- Mozgassuk a csúszóablakot a szövegen:
- Frissítsük a hash értéket egy új karakter hozzáadásával és az első karakter eltávolításával.
- Ha a hash érték megegyezik, végezzünk tényleges karakter-összehasonlítást a minta és az aktuális részlet között.
- Mozgassuk a csúszóablakot a szövegen:
- Találatok rögzítése:
- Jegyezzük fel a találatokat, ha a minta megegyezik a szöveg részletével.
Hash függvény
A hash függvény gyakran modulo műveletet használ a túlfutás elkerülésére: [ h(s) = (s[0] d^{m-1} + s[1] d^{m-2} + + s[m-1]) q ] ahol: - (d): az ábécé mérete (pl. 256 ASCII karakterekhez), - (q): egy nagy prímszám, amely minimalizálja a hash ütközéseket.
Pszeudokód
RabinKarp(text, pattern, d, q): n = text hossza m = pattern hossza h = d^(m-1) % q p_hash = 0 # Pattern hash t_hash = 0 # Szöveg hash # Kezdeti hash értékek számítása for i in 0 to m-1: p_hash = (d * p_hash + pattern[i]) % q t_hash = (d * t_hash + text[i]) % q for i in 0 to n-m: # Ha a hash értékek egyeznek, ellenőrizzük a mintát ha p_hash == t_hash: ha text[i:i+m] == pattern: visszaad találat # Hash érték frissítése ha i < n-m: t_hash = (d * (t_hash - text[i] * h) + text[i+m]) % q ha t_hash < 0: t_hash += q
Python implementáció
def rabin_karp(text, pattern, d=256, q=101):
n, m = len(text), len(pattern)
h = pow(d, m-1) % q
p_hash, t_hash = 0, 0
results = []
# Kezdeti hash értékek kiszámítása
for i in range(m):
p_hash = (d * p_hash + ord(pattern[i])) % q
t_hash = (d * t_hash + ord(text[i])) % q
for i in range(n - m + 1):
# Hash összehasonlítás
if p_hash == t_hash:
if text[i:i+m] == pattern:
results.append(i)
# Hash frissítése
if i < n - m:
t_hash = (d * (t_hash - ord(text[i]) * h) + ord(text[i + m])) % q
if t_hash < 0:
t_hash += q
return results
# Példa használat
text = "abracadabra"
pattern = "abra"
matches = rabin_karp(text, pattern)
print("Találatok indexei:", matches)
Kimenet:
Találatok indexei: [0, 7]
C++ implementáció
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<int> rabin_karp(const string& text, const string& pattern, int d = 256, int q = 101) {
int n = text.size();
int m = pattern.size();
int h = 1;
int p_hash = 0, t_hash = 0;
vector<int> results;
// Az "h" érték kiszámítása
for (int i = 0; i < m - 1; ++i) {
h = (h * d) % q;
}
// Kezdeti hash értékek kiszámítása
for (int i = 0; i < m; ++i) {
p_hash = (d * p_hash + pattern[i]) % q;
t_hash = (d * t_hash + text[i]) % q;
}
for (int i = 0; i <= n - m; ++i) {
// Hash értékek összehasonlítása
if (p_hash == t_hash) {
if (text.substr(i, m) == pattern) {
results.push_back(i);
}
}
// Hash frissítése
if (i < n - m) {
t_hash = (d * (t_hash - text[i] * h) + text[i + m]) % q;
if (t_hash < 0) {
t_hash += q;
}
}
}
return results;
}
int main() {
string text = "abracadabra";
string pattern = "abra";
vector<int> matches = rabin_karp(text, pattern);
cout << "Találatok indexei:";
for (int idx : matches) {
cout << " " << idx;
}
cout << endl;
return 0;
}
Kimenet:
Találatok indexei: 0 7
Összegzés
Előnyök:
- Hatékony több minta esetén: Hashing gyors összehasonlítást tesz lehetővé.
- Egyszerű implementáció: Könnyen érthető és általánosítható.
Hátrányok:
- Ütközések kezelése: Ha sok hash érték egyezik, a karakter-összehasonlítás megnövelheti a futási időt.
- Hash függvény érzékenysége: A teljesítmény függ a hash függvény minőségétől és a választott modultól ((q)).
A Rabin-Karp-algoritmus különösen hatékony több minta esetén vagy olyan helyzetekben, ahol a minták gyors előfeldolgozására van szükség.
- Rabin-Karp algoritmus - Értelmező szótár (MEK)
- Rabin-Karp algoritmus - Etimológiai szótár (UMIL)
- Rabin-Karp algoritmus - Szótár.net (hu-hu)
- Rabin-Karp algoritmus - DeepL (hu-de)
- Rabin-Karp algoritmus - Яндекс (hu-ru)
- Rabin-Karp algoritmus - Google (hu-en)
- Rabin-Karp algoritmus - Helyesírási szótár (MTA)
- Rabin-Karp algoritmus - Wikidata
- Rabin-Karp algoritmus - Wikipédia (magyar)