Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
прога_билеты.docx
Скачиваний:
2
Добавлен:
01.03.2025
Размер:
2.98 Mб
Скачать

Результат

Итого, на предподсчёт требуется   времени и памяти, а ответ на запрос вычисляется за  .

Поиск нескольких минимумов на отрезке. Задача поиска подстрок. Алгоритм Рабина-Карпа. Конечный автомат. Алгоритм Бойера-Мура.

Поиск нескольких минимумов на отрезке.

  1. Если требуется получать сразу несколько минимумов по отрезку (всегда n минимумов на отрезке) – делаем дерево отрезков с функцией нахождения этих нескольких минимумов (но придется делать k сравнений  в k раз усложняет время)

  2. Альтернатива

Надо найти k минимумов. Находим по RMQ – индекс первого. Потом запускаем RMQ на подмассивах, на которые делится наш массив найденным индексом. Так найдем уже 3 минимума. И т.д. (на 4 подмассивах и т.д.)

Поиск подстроки в строке.

Имеются строки   и   такие, что       и элементы этих строк   символы из конечного алфавита  . Говорят, что строка   встречается в строке   со сдвигом  , если   и   =  . Если строка   встречается в строке  , то   является подстрокой  . Требуется проверить, является ли строка   подстрокой  .

В задачах поиска традиционно принято обозначать шаблон поиска как needle а строку, в которой ведётся поиск — как haystack . Также обозначим через Σ алфавит, на котором проводится поиск.

Если считать, что строки нумеруются с 1, простейший алгоритм (англ. brute force algorithm, naïve algorigthm) выглядит так.

for i=0...|haystack|-|needle|

for j=1...|needle|

if haystack[i+j]<>needle[j]

then goto 1

output("Найдено: ", i+1)

1:

Простейший алгоритм поиска даже в лучшем случае проводит |haystack|−|needle|+1 сравнение; если же есть много частичных совпадений, скорость снижается до O(|haystack|·|needle|).

Показано, что примитивный алгоритм отрабатывает в среднем 2h сравнений

Метод хеширования

Для решения задачи удобно использовать полиномиальный хеш, так его легко пересчитывать:  , где   — это некоторое простое число, а   — некоторое большое число, для уменьшения числа коллизий (обычно берётся   или  , чтобы модуль брался автоматически при переполнении типов). Стоит обратить внимание, что если 2 строчки имеют одинаковый хэш, то они в большинстве таких случаев равны.

При удалении первого символа строки и добавлении символа в конец считать хеш новой строки при помощи хеша изначальной строки возможно за  :

.

.

Получается :  .

Следует учесть, что при получении отрицательного значения необходимо прибавить  .

Алгоритм

Алгоритм начинается с подсчета   и  .

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

Для ускорения работы алгоритма оптимально предпосчитать  .

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