Jump to content

Алгоритм Бойера – Мура – ​​Хорспула

Алгоритм Бойера – Мура – ​​Хорспула
Сорт Поиск подстроки
Структура данных Нить
Худшая производительность
Средняя производительность

В информатике алгоритм Бойера -Мура-Хорспула или алгоритм Хорспула — это алгоритм поиска подстрок в строках . Он был опубликован Найджелом Хорспулом в 1980 году под названием SBM. [ 1 ]

Это упрощение алгоритма поиска строк Бойера-Мура , который связан с алгоритмом Кнута-Морриса-Пратта . Алгоритм обменивает пространство на время, чтобы получить сложность среднего случая O (n) для случайного текста, хотя он имеет O(nm) в худшем случае , где длина шаблона равна m , а длина поиска строка равна n .

Описание

[ редактировать ]

Как и Бойер-Мур, Бойер-Мур-Хорспул предварительно обрабатывает шаблон, чтобы создать таблицу, содержащую для каждого символа алфавита количество символов, которые можно безопасно пропустить. Фаза предварительной обработки в псевдокоде выглядит следующим образом (для алфавита из 256 символов, т. е. байтов):

 // Unlike the original, we use zero-based indices here.
 function preprocess(pattern)
     T := new table of 256 integers
     for i from 0 to 256 exclusive
         T[i] := length(pattern)
     for i from 0 to length(pattern) - 1 exclusive
         T[pattern[i]] := length(pattern) - 1 - i
     return T

Поиск шаблона происходит следующим образом. Процедура поиск выдает индекс первого появления игла в стог сена .

// Compares two strings, up to the first len characters.
// Note: this is equivalent to !memcmp(str1, str2, len).
function same(str1, str2, len)
    i := len - 1
    // The original algorithm tries to play smart here: it checks for the
    // last character, and then starts from the first to the second-last.
    while str1[i] == str2[i]
        if i == 0
            return true
        i := i - 1
    return false

function search(needle, haystack)
    T := preprocess(needle)
    skip := 0
    // haystack[skip:] means substring starting at index `skip`. Would be &haystack[skip] in C.
    while length(haystack) - skip >= length(needle)
        if same(haystack[skip:], needle, length(needle))
            return skip
        skip := skip + T[haystack[skip + length(needle) - 1]]
    return -1

Производительность

[ редактировать ]

Алгоритм лучше всего работает с длинными игольными строками, когда он последовательно попадает в несовпадающий символ в последнем байте текущей позиции в стоге сена или рядом с ним, а последний байт иглы не встречается где-либо еще в иголке. Например, 32-байтовая игла, оканчивающаяся на «z», для поиска в 255-байтовом стоге сена, в котором нет байта «z», потребует до 224 байтовых сравнений.

Наилучший случай тот же, что и для алгоритма поиска строк Бойера-Мура в нотации большого О , хотя постоянные накладные расходы на инициализацию и для каждого цикла меньше.

Наихудшее поведение происходит, когда пропуск неправильных символов постоянно низкий (с нижним пределом перемещения в 1 байт) и большая часть иглы соответствует стогу сена. Пропуск плохого символа является низким только при частичном совпадении, когда последний символ стрелки также встречается в другом месте внутри стрелки, при этом перемещение на 1 байт происходит, когда один и тот же байт находится в обеих последних двух позициях.

Канонический вырожденный случай, аналогичный приведенному выше «лучшему» случаю, представляет собой иглу из байта «a», за которой следует 31 байт «z» в стоге сена, состоящем из 255 байтов «z». Это позволит выполнить 31 успешное сравнение байтов, сравнение 1 байта, которое завершится неудачно, а затем переместится на 1 байт вперед. Этот процесс повторится еще 223 раза (255–32), в результате чего общее количество сравнений байтов составит 7168 (32 × 224). (Другой цикл сравнения байтов будет иметь другое поведение.)

Наихудший случай значительно выше, чем для алгоритма поиска строк Бойера-Мура, хотя, очевидно, этого трудно достичь в обычных случаях использования. Также стоит отметить, что этот худший случай является и худшим случаем для наивного (но обычного) memcmp() алгоритм, хотя его реализация имеет тенденцию быть значительно оптимизированной (и более дружественной к кэшу).

Настройка цикла сравнения

[ редактировать ]

Исходный алгоритм имел более сложный цикл Same(). Прежде чем продолжить движение в положительном направлении, он использует дополнительную предварительную проверку: [ 1 ]

function same_orig(str1, str2, len)
    i ← 0
    if str1[len - 1] = str2[len - 1]
        while str1[i] = str2[i]
            if i = len - 2
                return true
            i ← i + 1
    return false

Настроенной версией алгоритма BMH является алгоритм Райта . Он добавляет дополнительную предварительную проверку среднего символа в порядке последний-первый-средний. Алгоритм переходит в полный цикл только тогда, когда проверка пройдена: [ 2 ]

function same_raita(str1, str2, len)
    i ← 0
    mid ← len / 2
    
    Three prechecks.
    if len ≥ 3
        if str[mid] != str2[mid]
            return false
    if len ≥ 1
        if str[0] != str2[0]
            return false
    if len ≥ 2
        if str[len - 1] != str2[len - 1]
            return false

    Any old comparison loop.
    return len < 3 or SAME(&str1[1], &str2[1], len - 2)

Неясно, сохраняет ли эта настройка 1992 года свое преимущество в производительности на современных машинах. Авторы аргументируют это тем, что реальный текст обычно содержит некоторые шаблоны, которые можно эффективно предварительно отфильтровать с помощью этих трех символов. Похоже, что Раита не знает о старой предварительной проверке последнего символа (он считал, что проверка только в обратном направлении). та же процедура реализована в Хорспуле), поэтому читателям рекомендуется относиться к результатам с недоверием. [ 2 ]

На современных машинах библиотеки функционируют как memcmp имеет тенденцию обеспечивать более высокую пропускную способность, чем любой из написанных вручную циклов сравнения. Поведение цикла «SFC» (терминология Хорспула) как в libstdc++, так и в libc++, похоже, предполагает, что современная реализация Raita не должна включать какие-либо односимвольные сдвиги, поскольку они отрицательно влияют на выравнивание данных. [ 3 ] [ 4 ] Также см. Алгоритм поиска строк , в котором подробно анализируются другие алгоритмы поиска строк.

Причины, по которым вам необходимо использовать алгоритм Хорспула

[ редактировать ]
  1. Эффективность алгоритма: количество сравнений между шаблоном и текстом сокращается, поскольку избегаются области текста, совпадение которых невозможно. Это дает алгоритму больше времени на более длинный текст.
  2. Простота: алгоритм сохраняет эффективный сдвиг плохих символов в подходе Бойера-Мура, но улучшает сдвиг хорошего суффикса, что значительно упрощает реализацию без ущерба для производительности. [ 5 ]
  1. ^ Jump up to: а б Хорспул, Р.Н. (1980). «Практический быстрый поиск в строках». Программное обеспечение: практика и опыт . 10 (6): 501–506. CiteSeerX   10.1.1.63.3421 . дои : 10.1002/спе.4380100608 . S2CID   6618295 .
  2. ^ Jump up to: а б Райта, Тимо (1992). «Настройка алгоритма поиска строк Бойера-Мура-Хорспула». Программное обеспечение: практика и опыт . 22 (10): 879–884. дои : 10.1002/сп.4380221006 . S2CID   14193323 .
  3. ^ «⚙ D27068 Улучшение string::find» . Обзор кода LLVM .
  4. ^ «[ИСПРАВЛЕНИЕ] улучшает алгоритм поиска строк» ​​. ССЗ .
  5. ^ Марнур, Сачин (19 апреля 2024 г.). «3 удивительных применения алгоритма Хорспула в DAA» . Проверено 31 августа 2024 г.
[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: b6e5c75780b5178409040dda1ac3d2ca__1725081900
URL1:https://arc.ask3.ru/arc/aa/b6/ca/b6e5c75780b5178409040dda1ac3d2ca.html
Заголовок, (Title) документа по адресу, URL1:
Boyer–Moore–Horspool algorithm - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)