Каковы правила сдвига для алгоритма поиска строк Бойера–Мура?

Я пытался понять правила сдвига в алгоритм поиска строк Бойера-Мура но не понял их. Я читал здесь на Википедия но это слишком сложно !

будет очень полезно, если кто-то перечислит правило простым способом.

3 ответов


в алгоритме Бойера-Мура вы начинаете сравнивать символы шаблона с текстовыми символами с конца шаблона. Если вы обнаружите несоответствие, у вас есть конфигурация типа

....xyzabc....      <-text
  ....uabc          <- pattern
      ^
    mismatch

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

что может быть сдвиг влево, если ситуация

     v
...xyzazc...
 ....uazc
 ..uazc

так что только это не гарантирует прогресса.

другая смена, хороший суффикс shift, выравнивает согласованную часть текста,m, С самым правым возникновением этой последовательности символов в шаблоне, которому предшествует другой символ (включая none, если соответствующий суффикс также является префиксом шаблона), чем соответствующий суффикс m шаблона-если такое происходит.

например

           v
....abcdabceabcfabc...
    ...xabcfabcfabc
        ...xabcfabcfabc

приведет к хорошему смещению суффикса из четырех позиций, так как согласованная часть m = abcfabc встречается в шаблоне в четырех местах слева от его суффикса-появления и предшествует там другому символу (x вместо f), чем в суффиксе позиция.

если нет полного вхождения совпадающей части в шаблон, которому предшествует другой символ, чем суффикс, хороший сдвиг суффикса выравнивает суффикс совпадающей части текста с префиксом шаблона, выбирая максимальное перекрытие, например

      v
...robocab....
    abacab
        abacab

хороший сдвиг суффикса всегда сдвигает шаблон вправо, поэтому гарантирует прогресс.

затем, при каждом несоответствии успехи плохого сдвига персонажа и хорошего суффикса сравниваются сдвиги, и выбирается больший. Это объясняется в большей глубине христианской Charras и Thierry Lecroq здесь, наряду со многими другими алгоритмами поиска строк.


для примера, который вы упомянули в комментариях,

SSIMPLE EXAMPLE
EXAMPLE
  ^

соответствующий суффикс MPLE, и несоответствующий текстовый символ I. Таким образом, плохой сдвиг персонажа ищет последнее появление I в первой части картины. Есть нет, так что плохой сдвиг характера будет сдвигать шаблон так, чтобы несоответствие I перед началом шаблона

SSIMPLE EXAMPLE
   EXAMPLE

и хороший сдвиг суффикса ищет самое правое вхождение MPLE в шаблоне не перед A, или самый длинный суффикс MPLE это префикс шаблона. В шаблоне перед суффиксом нет полного появления совпадающей части, поэтому самый длинный суффикс совпадающей части, который также префикс паттерна определяет хороший сдвиг суффикса. В этом случае два суффикса совпадающей части, которые являются префиксами шаблона, являются односимвольной строкой E и пустая строка. Самая длинная, очевидно, непустая строка, поэтому хороший сдвиг суффикса выравнивает односимвольный суффикс E в согласованной части текста с односимвольным префиксом шаблона

SSIMPLE EXAMPLE
      EXAMPLE

хороший сдвиг суффикса сдвигает шаблон дальше вправо, так что избранный сдвиг.

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

тогда у нас есть полное совпадение.

в варианте с узор TXAMPLE, хороший сдвиг суффикса обнаруживает, что ни один непустой суффикс совпадающей части не является префиксом шаблона (и нет никакого появления полной совпадающей части в шаблоне не предшествует A), поэтому хороший сдвиг суффикса выравнивает пустой суффикс совпадающей части текста (граница между E и Пробел) с пустым префиксом шаблона (пустая строка, предшествующая T), в результате чего в

SSIMPLE EXAMPLE
       TXAMPLE

(затем на следующем шаге смещение плохого символа выравнивает два Ls, и следующее несоответствие в шаге после этого происходит на начальном T шаблон).


есть хорошая визуализация здесь.

(EDIT: есть также очень хорошее объяснение с примерами и примером того, как реализовать шаги предварительной обработки здесь.)

общие правила:

  • мы ищем как выровнять шаблон с текстом, чтобы выровненные части совпадали. Если такого выравнивания не существует, шаблон не найден в тексте.
  • проверьте каждое выравнивание справа налево-то есть начните с проверки, соответствует ли последний символ шаблона его текущему выравниванию.
  • когда вы нажмете символ, который не выравнивается, увеличьте смещение (сдвиньте шаблон), чтобы последние появление буквы на стороне текста в шаблоне выровнено с этим появлением буквы на стороне текста, на которую мы сейчас смотрим. Это требует предварительного построения (или поиска каждый раз, но это менее эффективно) индекса, где каждая буква существует в шаблоне.
  • если символ, рассматриваемый в тексте, не отображается в шаблоне, пропустите вперед по всей длине шаблона.
  • если конец шаблона выступает за конец текста(смещение + длина(шаблон) > длина (Текст)), шаблон не отображается в тексте.

то, что я только что описал, - это правило "плохого характера". Правило "хорошего суффикса" дает еще один вариант сдвига; какой бы сдвиг дальше ни был тот, который ты должен взять. Вполне возможно реализовать алгоритм без правило хорошего суффикса, но оно будет менее эффективным, как только индексы будут построены.

правило хорошего суффикса требует, чтобы вы также знали, где найти каждую многосимвольную подстроку шаблона. Когда вы нажмете несоответствие (проверка, как всегда, справа налево), сдвиг хорошего суффикса перемещает шаблон в точку, где буквы, которые сделал уже матч будет делать Итак, еще раз. В качестве альтернативы, если часть, которая совпала, уникальна в шаблоне, вы знаете, что можете пропустить весь путь мимо нее, потому что если она не совпала, когда выстроилась с единственным вхождением, она не может совпадать, когда выстроилась с любой другой частью шаблона.

например, рассмотрим следующую ситуацию:

  • мой шаблон заканчивается на "собака".
  • в настоящее время я выровнял его с частью текста, которая заканчивается на " s собака."
  • таким образом, плохая буква - "s" (где они перестают совпадать), а хороший суффикс - "собака" (часть, которая совпадала).

У меня есть два варианта:

  1. Shift так, чтобы первая " s "(справа налево) в шаблоне была выровнена с " s " в тексте. Если в шаблоне нет "s", переместите начало шаблона сразу за "s".
  2. Shift так, чтобы следующая "собака" была выровнена с "собакой" в текст. Если в паттерне нет другой "собаки", переместите начало паттерна чуть дальше конца"собаки".

и я должен взять тот, который позволит мне сдвинуться дальше.

Если вы все еще смущены, попробуйте задать более конкретный вопрос; трудно быть ясным, когда мы не знаем, где вы застряли.


есть две эвристики: эвристика символа летучей мыши и эвристика хорошего шаблона.

во-первых, вы знаете, сравнение иглы начинается с ее конца. Итак, если символы не совпадают с иглой, то такой хотя бы сравниваемый символ в стоге сена будет соответствовать игле. Например. игла "ABRACADABRA", а текущий карактер в haystack - "B", он не соответствует последнему" A", а также не соответствует предыдущему" R", поэтому сдвиг на один бессмысленен, не будет совпадения. Но" Б " матч 2-й с конца персонаж игла. Таким образом, мы бы сдвинули иглу по крайней мере на 2 позиции. Если текущий символ в стоге сена не совпадает ни с одним в игле, игла должна быть смещена за пределы текущего символа. Другими словами, мы сдвигаем шаблон до тех пор, пока текущий символ в стоге сена не совпадет с символом в игле или вся игла не будет смещена за пределы.

количество сдвига вычисляется и сохраняется в массиве, поэтому для "абракадабры" это будет: ['R'] = 1, ['B'] = 2, ['D'] = 4 и т. д.

haystack: XYABRACADABRA...
                    |
needle:   ABRACADABRA
           ABRACADABRA <-- pointless shift: R will not match B
            ABRACADABRA

во-вторых, если найденный матч по крайней мере" ABRA "в haystack (но не полный матч) игла может быть сдвинута так, что следующий" ABRA " будет соответствовать.

величина сдвига за соответствием часть тоже учитывался: электронная. г. ['А'] = 3, ['РА'] = 11, ['БЮСТГАЛЬТЕР'] = 11, ['АБРА'] = 7, ['ДАБРА'] = 7...

haystack: XYZYXADABRACADABRA...
needle:   ABRACADABRA           (shift to ABRA from matched ADABRA)
          ~~~~   ~~~~
                 ABRACADABRA

это не полный explantaion всех случаях, но основная идея алгоритма.