Изменения

Перейти к: навигация, поиск
Псевдокод
{{Задача|definition ==Постановка задачи==Имеются строки <tex>s</tex> и <tex>t</tex> такие, что элементы этих строк <tex>-</tex> символы из конечного алфавита <tex> \Sigma </tex>. ГоворятТребуется найти такую строку <tex>z</tex> максимальной длины, что <tex>z</tex> является и подстрокой <tex>s</tex>, и подстрокой <tex>t</tex>.}}{{Определение|definition = Будем говорить, что строка <tex>z[0 \, \ldots \, m-1 .. m]</tex> является подстрокой строки <tex>s[0 \, \ldots \, n-1 .. n]</tex>, если существует такой индекс <tex>k \in [0 .. \, \ldots \, n - m]</tex>, что для любого <tex>i \in [0 \, \ldots \, m-1 .. m]</tex> справедливо <tex>s[k + i] = z[i]</tex>. Требуется найти такую строку <tex>z</tex> максимальной длины, что <tex>z</tex> является и подстрокой <tex>s</tex>, и подстрокой <tex>t</tex>.}}
==Алгоритм==Пусть длина наибольшей общей подстроки будет <tex>x</tex>. Заметим, что у строк <tex>s</tex> и <tex>t</tex> обязательно найдется общая подстрока длины <tex>y \in [0 .. \ldots x]</tex>, так как в качестве такой строки можно взять префикс наибольшей общей подстроки. Рассмотрим предикат <tex>f \colon [0 .. \ldots \min(|s|, |t|)] \rightarrow \{0, 1\}</tex>, который для <tex>i</tex> из области определения истинен, если у строк <tex>s</tex> и <tex>t</tex> есть общая подстрока длины <tex>i</tex>, иначе ложен. Согласно замечанию, предикат <tex>f</tex> должен по мере возрастания <tex>i</tex> быть истинным до некоторого момента, а затем обращаться в ложь. Собственно, максимальное значение, при котором предикат истинен, является длиной наибольшей общей подстроки. Таким образом, требуется с помощью [[Целочисленный двоичный поиск|двоичного поиска]] найти это значение. В ходе работы придется проверять наличие общей подстроки заданной длины. Для этого будем использовать хеширование, чтобы улучшить асимптотику алгоритма. Алгоритм является эвристическим и может выдавать неверный ответ, так как совпадение хешей строк не гарантирует равенство строк. Поэтому нужно выполнить проверку нескольких случайных символов подстрок на совпадение, проиграв при этом по времени работы. Алгоритм работает следующим образом:
1) У * у строки <tex>s</tex> хешируем подстроки заданной длины и полученные хеши записываем в Set.,
2) У * у строки <tex>t</tex> хешируем подстроки заданной длины и в случае совпадения хеша с элементом Set проверяем несколько случайных символов подстрок на совпадение.
Хеширование будем производить так же, как и в [[Поиск подстроки в строке с использованием хеширования. Алгоритм Рабина-Карпа|алгоритме Рабина-Карпа]].
<tex>i</tex> — длина подстроки, найденная с помощью [[Целочисленный двоичный поиск|двоичного поиска]].
<tex>f(i)</tex> — функцияпредикат, описанная описанный в алгоритме.
<tex>'''bool''' f(i: '''int''')</tex>: Записываем в <tex>Set</tex> hashes = хеши подстрок строки <tex>s</tex> длины <tex>i</tex> '''for''' <tex>j = 1...0 '''to''' |t| - i + 1</tex> Считаем хеш подстроки <tex>hash = hash(t[j ... j + i - 1]</tex>) '''if''' хеш содержится в <tex>Set</tex>hash '''in''' hashes
'''if''' совпали несколько случайных символов подстрок
'''return''' 1''true''
'''else'''
'''continue'''
'''return''' 0''false''
==Время работы==Проведем оценку асимптотики времени работы предложенного алгоритма. Посмотрим, сколько нам потребуется действий на каждом шаге двоичного поиска. Во-первых, хеширование подстрок строки <tex>s</tex> и запись их в Set требует <tex>O(|s|)</tex> шагов. Во-вторых, хеширование подстрок строки <tex>t</tex> и проверка их наличия в Set требует <tex>O(|t|)</tex>. Проверка на совпадение нескольких символов подстрок требует константное время. Значит, на каждый шаг двоичного поиска требуется <tex>O(\max(|s|, |t|))</tex> действий. Заметим, что всего для завершения двоичного поиска потребуется <tex>O(\log(\min(|s|, |t|)))</tex> шагов. Следовательно, суммарное время работы алгоритма будет <tex>O(\log(\min(|s|, |t|)) \cdot \max(|s|, |t|))</tex> действий.
== Литература См. также ==* [[Поиск подстроки в строке с использованием хеширования. Алгоритм Рабина-Карпа]]* [[Задача о наибольшей общей подпоследовательности]] == Источники информации ==* ''Кормен Т, Томас Х., Лейзерсон Ч, Чарльз И., Ривест Р, Рональд Л. , Штайн Клиффорд'' '''Алгоритмы: построение и анализ. — 2''', 3издиздание. Пер. с англ. — М.: Издательский дом «Вильямс»"Вильямс", 20072014. — 1328 с.: ил. — СISBN 978-5-8459-1794-2 (рус. 1296) — страницы 1036–1041.
[[Категория:Алгоритмы и структуры данных]]
[[Категория:Поиск подстроки в строке]]
[[Категория:Точный поиск]]
[[Категория:Хеширование]]
442
правки

Навигация