Knuth-Morris-Pratt-algoritmus
Kiejtés
- IPA: [ ˈknuthmorːiʃprɒtːɒlɡoritmuʃ]
Főnév
Knuth-Morris-Pratt algoritmus (KMP)
A Knuth-Morris-Pratt (KMP) algoritmus egy hatékony sztringkeresési algoritmus, amely egy szövegben találja meg egy adott minta előfordulását. Az algoritmus előfeldolgozza a mintát, hogy gyorsabban találhassa meg a lehetséges egyezéseket, elkerülve az ismételt összehasonlításokat.
Elmélet
- Alapprobléma:
- Adott egy szöveg ((T)) és egy minta ((P)).
- Az algoritmus célja, hogy megtalálja, hol (ha egyáltalán) fordul elő (P) a (T)-ben.
- Előfeldolgozás:
- Létrehoz egy részleges egyezési táblázatot (prefix-funkció), amely megmutatja, hogy a minta bizonyos részének melyik előző része egyezhet.
- Ez lehetővé teszi az algoritmus számára, hogy elkerülje az ismételt összehasonlításokat, ha egy részleges egyezés megszakad.
- Kulcsgondolat:
- Ha a minta (P) részben illeszkedik a szöveghez, és egy eltérés történik, akkor a részleges egyezési táblázat segítségével gyorsan megállapítható, hogy a minta melyik pozíciójában folytatható az összehasonlítás.
Időkomplexitás
- Előfeldolgozás: (O(m)), ahol (m) a minta hossza.
- Keresés: (O(n)), ahol (n) a szöveg hossza.
- Összesen: (O(n + m)).
Pszeudokód
Előfeldolgozás (Prefix-függvény kiszámítása)
ComputePrefixFunction(P): m = P hossza pi = [0] * m // Prefix-függvény j = 0 // Prefix hossza ciklus i = 1-től m-1-ig: amíg j > 0 és P[i] != P[j]: j = pi[j - 1] ha P[i] == P[j]: j = j + 1 pi[i] = j térj vissza pi
KMP keresés
KMP(T, P): n = T hossza m = P hossza pi = ComputePrefixFunction(P) j = 0 // Minta pozíciója ciklus i = 0-tól n-1-ig: amíg j > 0 és T[i] != P[j]: j = pi[j - 1] ha T[i] == P[j]: j = j + 1 ha j == m: return i - m + 1 // Talált egyezés kezdőpozíciója j = pi[j - 1] térj vissza -1 // Nincs egyezés
Python implementáció
def compute_prefix_function(pattern):
m = len(pattern)
pi = [0] * m
j = 0 # Prefix hossza
for i in range(1, m):
while j > 0 and pattern[i] != pattern[j]:
j = pi[j - 1]
if pattern[i] == pattern[j]:
j += 1
pi[i] = j
return pi
def kmp_search(text, pattern):
n = len(text)
m = len(pattern)
pi = compute_prefix_function(pattern)
j = 0 # Minta pozíciója
for i in range(n):
while j > 0 and text[i] != pattern[j]:
j = pi[j - 1]
if text[i] == pattern[j]:
j += 1
if j == m:
return i - m + 1 # Egyezés kezdőpozíciója
j = pi[j - 1]
return -1 # Nincs egyezés
# Példa használat
text = "ababcabcabababd"
pattern = "ababd"
result = kmp_search(text, pattern)
print(f"A minta kezdőpozíciója: {result}" if result != -1 else "Nincs egyezés.")
Kimenet:
A minta kezdőpozíciója: 10
C++ implementáció
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<int> compute_prefix_function(const string& pattern) {
int m = pattern.size();
vector<int> pi(m, 0);
int j = 0;
for (int i = 1; i < m; ++i) {
while (j > 0 && pattern[i] != pattern[j]) {
j = pi[j - 1];
}
if (pattern[i] == pattern[j]) {
j++;
}
pi[i] = j;
}
return pi;
}
int kmp_search(const string& text, const string& pattern) {
int n = text.size();
int m = pattern.size();
vector<int> pi = compute_prefix_function(pattern);
int j = 0;
for (int i = 0; i < n; ++i) {
while (j > 0 && text[i] != pattern[j]) {
j = pi[j - 1];
}
if (text[i] == pattern[j]) {
j++;
}
if (j == m) {
return i - m + 1; // Egyezés kezdőpozíciója
}
}
return -1; // Nincs egyezés
}
int main() {
string text = "ababcabcabababd";
string pattern = "ababd";
int result = kmp_search(text, pattern);
if (result != -1) {
cout << "A minta kezdőpozíciója: " << result << endl;
} else {
cout << "Nincs egyezés." << endl;
}
return 0;
}
Kimenet:
A minta kezdőpozíciója: 10
Összegzés
Előnyök:
- Hatékonyság: (O(n + m)) időben működik, még a legrosszabb esetben is.
- Előfeldolgozás: Az ismétlődő összehasonlítások minimalizálása a prefix-függvénnyel.
Hátrányok:
- Komplexitás: Az algoritmus implementálása bonyolultabb, mint a naiv sztringkeresés.
A KMP algoritmus kiváló választás nagy szövegek gyors keresésére, például DNS-keresés, szövegbányászat vagy kódegyezés esetén.
- Knuth-Morris-Pratt-algoritmus - Értelmező szótár (MEK)
- Knuth-Morris-Pratt-algoritmus - Etimológiai szótár (UMIL)
- Knuth-Morris-Pratt-algoritmus - Szótár.net (hu-hu)
- Knuth-Morris-Pratt-algoritmus - DeepL (hu-de)
- Knuth-Morris-Pratt-algoritmus - Яндекс (hu-ru)
- Knuth-Morris-Pratt-algoritmus - Google (hu-en)
- Knuth-Morris-Pratt-algoritmus - Helyesírási szótár (MTA)
- Knuth-Morris-Pratt-algoritmus - Wikidata
- Knuth-Morris-Pratt-algoritmus - Wikipédia (magyar)