Alt sətir axtarışı text içində pat nümunəsinin bütün yerlərini tapmaq məsələsidir (n = len(text), m = len(pat)). Sadə üsul O(nm) vaxt aparır. Rabin-Karp alqoritmi hər pəncərəni simvol-simvol yox, yuvarlanan hesh ilə müqayisə edir və orta halda O(n + m) işləyir. Sətirlərlə iş: palindrom və anaqramlar.

`aaab` nümunəsi `aaaaaaaa` mətnində: hər sürüşmədə 4 müqayisə
aaab nümunəsi aaaaaaaa mətnində: hər sürüşmədə 4 müqayisə

Sadə axtarış

Nümunəni mətnin hər i mövqeyinə (0..n-m) qoyub soldan sağa müqayisə edirik; uyğunsuzluqda bir mövqe sürüşürük. Mövqelərin sayı n - m + 1, hər birində ən çox m müqayisə, deməli ən pis halda O(nm). Adi mətndə uyğunsuzluq adətən ilk simvollarda tapılır və vaxt O(n)-ə yaxın olur, lakin aaaa...ab kimi təkrarlı verilənlərdə (DNT, ikili mətnlər) ən pis hal real olur. Yaddaş O(1).

python
def naive(text, pat):
    n, m = len(text), len(pat)
    result, comps = [], 0
    for i in range(n - m + 1):
        j = 0
        while j < m:
            comps += 1
            if text[i + j] != pat[j]:
                break
            j += 1
        if j == m:
            result.append(i)
    return result, comps

print(naive("abracadabra", "abra"))
print(naive("a" * 20, "a" * 9 + "b"))
text
([0, 7], 16)
([], 110)

Yuvarlanan hesh

Əsası 10 olan hesh `3 1 4 1 5 9` üzərində: pəncərə sürüşəndə `O(1)`-də yenilənir
Əsası 10 olan hesh 3 1 4 1 5 9 üzərində: pəncərə sürüşəndə O(1)-də yenilənir

Sətri əsası B olan ədəd kimi oxuyuruq: h(s) = s[0]·B^(m-1) + s[1]·B^(m-2) + ... + s[m-1], nəticəni böyük sadə M-ə görə qalıqla saxlayırıq. Pəncərə bir simvol sağa sürüşəndə yeni heş köhnədən O(1)-də alınır: h_new = (h_old - s[i]·B^(m-1))·B + s[i+m] (mod M). Burada B^(m-1) mod M əvvəlcədən bir dəfə hesablanır (pow(B, m - 1, M)).