Алгоритм поиска строки Бойера — Мура считается наиболее быстрым среди алгоритмов общего назначения, предназначенных для поиска подстроки в строке. Был разработан Робертом Бойером и Джеем Муром в 1977 году. Преимущество этого алгоритма в том, что ценой некоторого количества предварительных вычислений над шаблоном (но не над строкой, в которой ведётся поиск) шаблон сравнивается с исходным текстом не во всех позициях — часть проверок пропускаются как заведомо не дающие результата.
Мы с Вами уже рассмотрели 2 подхода поиска подстроки: в лоб и Кнута - Морриса - Пратта.
И хотя последний можно отнести к правильным, сегодня мы разберем подход, являющийся классикой в решении данной задачи.
Простота, является характеристикой правильного решения и тривиальность данного подхода это подтверждает.
Основная идея алгоритм - начать поиск не с начала, а с конца подстроки. Наткнувшись на несовпадение, мы просто смещаем подстроку до самого правого вхождения данного символа.
Пример можете посмотреть в картинке заголовка :)
Можно заметить, что, как и в случае Кнута-Морриса-Пратта, мы так же можем осуществить предкомпиляцию выражения.
Для этого удобно в словарь заносить пары ключ = числовое значение символа(ord), значение = порядковый номер в подстроке.
А вот и реализация:
def bmPredCompil(x):
d = {}
lenX = len(x)
for i in xrange(len(x)):
# сколько символов с правого края до этой буквы
d[ord(x[i])] = lenX - i
return d
Осталось осуществить сам поиск со сдвигом:
def boyerMurSearch(s, x):
d = bmPredCompil(x)
# k - проход по s
# j - проход по x
# i - место начала прохода по s
lenX = i = j = k = len(x)
while j > 0 and i<=len(s):
# совпали, двигаемся дальше (от конца к началу)
if s[k-1] == x[j-1]:
k -= 1
j -= 1
# иначе, продвигаемся по строке на d и начинаем с правого конца подстроки снова
else:
i += d[ord(s[i])]
j = lenX
k = i
if j <= 0:# нашли
return k
return None # не нашли
Вот собственно и все! :)
Реализация, как и сама идея, достаточно прозрачна.

Это алгоритм Бойера - Мура - Хорспула!
ОтветитьУдалить