Алгоритм поиска подстроки в строке с помощью суффиксного массива — различия между версиями
| Строка 9: | Строка 9: | ||
==Улучшение бинарного поиска== | ==Улучшение бинарного поиска== | ||
| + | |||
| + | При двоичном поиске обозначим левую и правую границы текущего интервала как <tex> L </tex> и <tex> R </tex> соответственно. Изначально <tex> L = 0 </tex>, <tex> R = |S| - 1 </tex>. На каждой итерации будем сравнивать образец <tex> P </tex> с суффиксом <tex> sufArray[(L + R) / 2] </tex>. Обозначим за <tex> left </tex> длину общего префикса <tex> P </tex> и <tex> sufArray[L] </tex>, а за <tex> right </tex> длину общего префикса <tex> P </tex> и <tex> sufArray[R] </tex>. Также обозначим за <tex> minRange </tex> минимум из <tex> left </tex> и <tex> right </tex>. Значение <tex> minRange </tex> будем поддерживать на каждой итерации двоичного поиска. Теперь, зная <tex> minRange </tex>, можно начинать сравнение образца <tex> P </tex> с суффиксом <tex> sufArray[(L + R) / 2] </tex>, начиная с <tex> minRange + 1 </tex> символа. Это возможно, так как для любого суффикса из нашей границы от <tex> L </tex> до <tex> R </tex> первые <tex> minRange </tex> символов совпадают. Если бы это было не так, то в суффиксном массиве в границе от <tex> L </tex> до <tex> R </tex> были бы суффиксы, которые сначала имеют <tex> minRange </tex> совпадений, затем не имеют, а затем снова имеют, что говорит о неправильном построении суффиксного массива. <br> | ||
| + | При таком поиске время работы равно <tex> O(|P| + log|S|) </tex>. | ||
Версия 05:43, 1 мая 2011
Пусть у нас есть образец , строка и суффиксный массив . Мы хотим найти все вхождения данного образца в данную строку.
Решение при помощи бинарного поиска
Понятно, что если образец входит в строку , то он является префиксом какого-нибудь ее суффикса. Если вхождений несколько, то в суффиксном массиве они будут находиться рядом друг с другом. Получается, что задача сводится к бинарному поиску в упорядоченном массиве.
Определим границы, в которых лежат вхождения. На первом шаге сравниваем суффикс и образец . Если суффикс лексикографически больше, то необходимо идти в левую половину , иначе в правую. На следующем шаге аналогично проверяем суффикс по середине от половины суффискного массива, затем от четверти и так далее. В результате проделанной работы получим левую и правую границы и соответственно. В этих границах и лежат вхождения образца в строку .
Время лексикографического сравнения образца с суффиксом равно длине их общего префикса и не может превышать . Поэтому время работы алгоритма равно .
Улучшение бинарного поиска
При двоичном поиске обозначим левую и правую границы текущего интервала как и соответственно. Изначально , . На каждой итерации будем сравнивать образец с суффиксом . Обозначим за длину общего префикса и , а за длину общего префикса и . Также обозначим за минимум из и . Значение будем поддерживать на каждой итерации двоичного поиска. Теперь, зная , можно начинать сравнение образца с суффиксом , начиная с символа. Это возможно, так как для любого суффикса из нашей границы от до первые символов совпадают. Если бы это было не так, то в суффиксном массиве в границе от до были бы суффиксы, которые сначала имеют совпадений, затем не имеют, а затем снова имеют, что говорит о неправильном построении суффиксного массива.
При таком поиске время работы равно .