Изменения

Перейти к: навигация, поиск

Алгоритм Ландау-Вишкина (k несовпадений)

149 байт добавлено, 20:38, 22 марта 2017
м
Пример
Заметим, если <tex>tm[i][k+1] = m+1</tex>, то подстрока <tex>y[i+1...i+m]</tex> отличается от образца <tex>x</tex> не более, чем на <tex>k</tex> символов, и, таким образом, является решением задачи.
Затем образец сканируется параллельно с текстом слева на права направо по одному символу за раз. На итерации <tex>i</tex> с образцом сравнивается подстрока <tex>y[i+1...i+m]</tex>. Пусть <tex>j</tex> {{---}} это самая правая позиция в тексте, достигнутая за предыдущие итерации, то есть <tex>j</tex> является максимальным из чисел <tex>r+tm[r][k + 1]</tex>, где <tex>0 \leqslant r < i</tex>. Если <tex>i < j</tex>, в <tex>b</tex> присваивается результат работы <tex>\mathrm{merge}</tex>, которая находит количество несовпадений между <tex>x[1...j-i]</tex> и <tex>y[i+1...j]</tex>. Если <tex>b</tex> не превышает <tex>k</tex>, вызывается процедура <tex>\mathrm{extend}</tex>, которая сравнивает подстроки <tex>y[j + 1...i + m]</tex> и <tex>x[j - i + 1...m]</tex>, где изменяется таблица текстовых несовпадений. Переменная <tex>r</tex> будет рассмотрена ниже.
{| border="0"
[[Файл:algLandauVishkin2.png|thumb|380px|right| Синие подстроки сравниваются в процедуре <tex>\mathrm{extend}</tex>. <tex>w < k + 1</tex>]]
Рассмотрим процедуру <tex>\mathrm{extend}</tex> подробнее. Она сравнивает подстроки <tex>y[j + 1...i + m]</tex> и <tex>x[j - i + 1...m]</tex>, в случае несовпадения <tex>b</tex> увеличивается , и таблица текстовых несовпадений обновляется. Это происходит пока либо не будет найдено <tex>k + 1</tex> несовпадений (учитывая несовпадения, которые были найдены раньше на <tex>i</tex>-ой итерации), либо не будет достигнуто <tex>y[i+m]</tex> с не больше чем <tex>k</tex> несовпадениями, то есть найдено вхождение образца, начинающееся с <tex>y[i+1]</tex>.
{| border="0"
|align="left" colspan="4"|
<font size=2>
'''void''' extend(i : '''int''', j : '''int''', b : '''int''') '''while''' (b < k + 1) '''and''' (j - i < m) j++ '''if''' y[j] <tex>\neq</tex> x[j-1] b++ tm[i][b] = j - i
</font>
|}
v = q
'''while''' (b < k + 1) '''and''' (v < k + 2) '''and''' (i + pm[i - r][u] < j '''or''' tm[r][v] <tex>\neq</tex> m + 1)
'''if''' i + pm[i - r][u] > r + tm[r][v] <font color=green> // Случай 2, условие A </font>
b++
tm[i][b] = tm[r][v] - (i - r)
tm[i][b] = pm[i - r][u]
u++
'''else''' '''if''' i + pm[i - r][u] = r + tm[r][v] <font color=green> // Случай 3 </font>
'''if''' x[pm[i - r][u]] <tex>\neq</tex> y[i + pm[i - r][u]]
b++
|align="left" colspan="4"|
<font size=2>
'''void''' precalc pm precalcPm()
pm[<tex>2^{s-1}</tex>...<tex>2^{s} - 1</tex>][1...min{<tex>2^{\log (m-1)}2k - 1</tex>, <tex>m - 2^{s}</tex>}] = m + 1
r = <tex>2^{s-1}</tex>
Рассмотрим построение <tex>pm</tex>. Используя аргументы, аналогичные применявшимся при проверке корректности процедуры <tex>\mathrm{merge}</tex>, можно показать, что для нахождения требуемого количества несовпадений на стадии <tex>s</tex> требуется <tex>\min\{2^{\log(m)-s}4k+1, m-2^{s}\}</tex> позиций, для которых выполняется ''условие B'', и в особом случае, а именно, на стадии <tex>\log m</tex>, требуется <tex>4k + 1</tex> таких позиций.
На каждой стадии <tex>s</tex> из <tex>\log m</tex> стадий анализа образца цикл <tex>\mathrm{for}</tex> производит <tex>2^{s-1}</tex> итераций <tex>(2^{s-1} \leqslant i \leqslant 2^{s}-1)</tex>. Если не считать время работы процедур <tex>\mathrm{merge}</tex> и <tex>\mathrm{extend}</tex>, каждая итерация требует фиксированного времени. Для всех итераций на шаге <tex>s</tex> процедуре <tex>\mathrm{extend}</tex> требуется время <tex>O(m)</tex>. Ранее было показано, что время работы <tex>\mathrm{merge}</tex> пропорционально числу искомых несовпадений. Таким образом, каждый вызов <tex>\mathrm{merge}</tex> занимает время <tex>O(\min\{2^{\log(m)-s}4k+1, m-2^{s}\})</tex>, что равно <tex>O(2k2^{\log (m)-s})</tex>. Таким образом, общее время для стадии <tex>s</tex> равно <tex>O(m+2^{s-1}(2k2^{\log (m) -s}))</tex> = <tex>O(km)</tex>. Проведя суммирование по всем стадиям, получаем общее время счета <tex>O</tex> <tex>\displaystyle \left(\sum_{i=1}^{\log m} km\right) = O(dkm km \log m)</tex>. Таким образом, общие затраты времени, включающие предварительную обработку образца и анализ текста, равны <tex>O(k(n + m \log m))</tex>.
==Пример==
{| class="wikitable" cellpadding="4" border="1" style="border-collapse: collapse; text-align: center;"
|-
| tm || '''1''' || '''2''' || '''3''' || x[1..<tex>\ldots</tex> m] || y[i+1..<tex>\ldots</tex> i+m]
|-
| '''0''' || 2 || 3 || 4 || '''t'''ram || '''t'''het
{| class="wikitable" cellpadding="4" border="1" style="border-collapse: collapse; text-align: center;"
|-
| pm || '''1''' || '''2''' || '''3''' || '''4''' || '''5''' || x[1..<tex>\ldots</tex> m-i] || x[i+1..<tex>\ldots</tex> m]
|-
| '''1''' || 1 || 2 || 3 || 5 || 5 || tra || ram
[[Категория: Алгоритмы и структуры данных]]
[[Категория: Поиск подстроки в строке]]
[[Категория: Нечёткий поиск]]
276
правок

Навигация