Изменения

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

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

2054 байта добавлено, 19:37, 4 сентября 2022
м
rollbackEdits.php mass rollback
'''Постановка задачи:''' Дано дано число <tex>k > 0</tex> текст <tex>y[1...n]</tex> и образец <tex>x[1...m]</tex>, <tex>m < n</tex>. Требуется найти все подстроки текста длины <tex>m</tex>, с не более чем <tex>k</tex> несовпадающими символами с образцом. Эту задачу решает алгоритм Ландау-Вишкина (k несовпадений) (''англ.Landau-Vishkin Algorithm'')
==Алгоритм==
===Идея===
[[Файл:algLandauVishkin1.png|thumb|380px250px|right| Красным отмечены несовпадения. В таблицу <tex>tm </tex> по номеру несовпадения записывается соответстующий индекс образца, то есть <tex>tm[i][1] = a</tex>, <tex>tm[i][2] = b</tex>, <tex>tm[i][3] = c</tex> и т . д.]]
При анализе используется двумерный массив несовпадений текста <tex>tm[0...n-m][1...k+1]</tex>, содержащий информацию о несовпадениях текста с образцом. По завершении анализа в его <tex>i</tex>-й строке содержатся позиции в <tex>x</tex> первых <tex>k+1</tex> несовпадений между строками <tex>x[1...m]</tex> и <tex>y[i+1...i+m]</tex>. Таким образом, если <tex>tm[i][v] = s</tex>, то <tex>y[i+s] \neq x[s]</tex>, и это <tex>v</tex>-е несовпадение между <tex>x[1...m]</tex> и <tex>y[i+1...i+m]</tex>, считая слева направо. Если число <tex>d</tex> несовпадений <tex>x[1...m]</tex> с подстрокой <tex>y[i+1...i+m]</tex> меньше <tex>k+1</tex>, то, начиная с <tex>d+1</tex>, элементы <tex>i</tex>-й строки равны значению по умолчанию <tex>m+1</tex>. (См. [[Алгоритм Ландау-Вишкина (k несовпадений)#Пример|пример]]).
Заметим, если <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"
|align="left" colspan="4"|
<font size=2>
'''int[][]''' algorithmLandauViskin(y : '''string''', x : '''string''') n = y.length m = x.length tm[0...n-m][1...k+1] = m+1 <font color=green> // инициализация</font> r = 0 j = 0 '''for ''' i = 0 to n - m b = 0 '''if ''' i < j b = merge(i, r, j) '''if ''' b < k + 1 r = i extend(i, j, b) '''return''' tm
</font>
|}
===Процедура extend===
[[Файл: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>
|}
===Процедура merge===
[[Файл:algLandauVishkin3.png|thumb|380px400px|right| Синие подстроки сравниваются в процедуре <tex>\mathrm{merge. Красным отмечены несовпадения}</tex>.]]
Рассмотрим процедуру <tex>\mathrm{merge}</tex> подробнее. Она находит количество несовпадений между <tex>x[1... j-i]</tex> и <tex>y[i+1...j]</tex> и устанавливает <tex>b </tex> равным найденному числу, при этом используется полученая полученная ранее информация. Введем <tex>r</tex> {{-- -}} это строка таблицы несовпадений, в которой есть информация о несовпадениях, полученных при совмещении начала образца и <tex>y[r+1]</tex>. Текущий номер самой правой из проверенных на настоящий момент позиции текста равен <tex>r+tm[r][k+1]</tex> содержит текущий номер самой правой из проверенных на настоящий момент позиций текста. Поэтому при обработки построки подстроки начинающейся с <tex>y[i+1]</tex>, можно учитывать информацию в <tex>r</tex>-ой строке <tex>tm</tex>, которая содержит информацию о сопоставлении образца с <tex>y[i]</tex>. Подходящими значениями из таблицы несовпадений являются, таким образом, <tex>tm[r][q ... k+1]</tex>, где <tex>q</tex> {{---}} это наименьшее из целых чисел, для которых <tex>r+tm[r][q] > i</tex>. Однако, следует учитывать тот факт, что эти несовпадения соответствуют началу образца, выравниваемому который был выровнен с <tex>y[r+1]</tex>, в то время как текущая позиция образца выровнена с <tex>y[i+1]</tex> {{---}} разница в <tex>i - r</tex> мест.
[[Файл:algLandauVishkin4.png|thumb|380px250px|right| В таблицу <tex>pm </tex> по номеру несовпадения записывается соответстующий соответствующий индекс верхнего образца, то есть <tex>pm[i][1] = a</tex>, <tex>pm[i][2] = b</tex>, <tex>pm[i][3] = c</tex> и т д.]]
Также в алгоритме используется двумерный массив несовпадений образца <tex>pm[1...m-1][1...2k+1]</tex>, генерируемой на стадии предварительной обработки образца. В нем содержатся позиции несовпадения образца с самим собой при различных сдвигах, аналогично <tex>tm</tex>, то есть ест{{---}}ь в <tex>i</tex>-ой строке содержитатся содержатся позиции внутри <tex>x</tex> первых <tex>2k+1</tex> несовпадений между подстроками <tex>x[1...m-i]</tex> и <tex>x[i+1...m]</tex>. Таким образом, если <tex>pm[i, ][v] = s</tex>, то <tex>x[i+s] \neq x[s]</tex>, и это <tex>v</tex>-е несовпадение между <tex>x([1, ...m-i)]</tex> и <tex>x([i+1, ...m)]</tex> слева направо. Если число <tex>d</tex> несовпадений между этими строками меньше <tex>2k+1</tex>, то, начиная с <tex>d+1</tex>, элементы <tex>i</tex>-й строки равны <tex>m+1</tex>, значению по умолчанию. Построение <tex>tm</tex> будет подробнее рассмотрено позднее.
Таким образом, для <tex>\mathrm{merge}</tex> интерес представляет строка <tex>i - r</tex> таблицы несовпаденийобразца, причем используются значения <tex>pm[i-r][1...t]</tex>, где <tex>t</tex> {{---}} самое правое несовпадение в <tex>pm[i-r][1...2k+1]</tex>, такое, что <tex>pm[i-r][t] < j-i+1</tex>, так как требуются только несовпадения в подстроке <tex>x[1...j-i]</tex>.
Чтобы использовать упомянутую информацию в процедуре <tex>\mathrm{merge}</tex>, рассмотрим в тексте позицию <tex>p</tex>, находящуюся в диапазоне, <tex>i+1 < p < j</tex>. Рассмотрим следующие условия для позиции <tex>p</tex>:
'''Условие A''': когда символы <tex>x[1]</tex> и <tex>y[r+1]</tex> совмещены, позиция <tex>p</tex> в тексте соответствует предварительно выявленному несовпадению между образцом и текстом, то есть <tex>y[p] \neq x[p-r]</tex>, и это несовпадение номер <tex>v</tex>, где <tex>q < v < k+1</tex>, то есть <tex>p - r = tm[Файл:algLandauVishkin5.png|thumb|380px|right| Условие Ar][v]</tex>.
'''Условие A''': когда символы <tex>x[1]</tex> и <tex>y[r+1]</tex> совмещены, позиция <tex>p</tex> в тексте соответствует предварительно выявленному несовпадению между образцом и текстом, то есть <tex>y[p] \neq x[p-r]</tex>, и это несовпадение номер <tex>v</tex>, где <tex>q < v < k+1</tex>, то есть <tex>p - r = tm[rФайл:algLandauVishkin5.png|380px][v]</tex>.
'''Условие B''': для двух копий образца, со сдвигом относительно друг друга <tex>i - r</tex>, совмещенных с текстом так, что их начальные символы лежат, соответственно, над <tex>y[r+1]</tex> и <tex>y[i+1]</tex>, позиция <tex>p</tex> соответствует несовпадению между двумя образцам, то есть <tex>x[p-r] \neq x[Файл:algLandauVishkin6p-i]</tex>.png|thumb|380px|right| Условие BЭто <tex>u</tex>-е несовпадение при этом сдвиге, где <tex>1 < u < t</tex>, то есть <tex>p-i = pm[i-r][u]</tex>.
'''Условие B''': для двух копий образца, со сдвигом относительно друг друга <tex>i - r</tex>, совмещенных с текстом так, что их начальные символы лежат, соответственно, над <tex>y[r+1]</tex> и <tex>y[i+1]</tex>, позиция <tex>p</tex> соответствует несовпадению между двумя шаблонами, то есть <tex>x[p-r] \neq x[p-i]</tex>Файл:algLandauVishkin6. Это <tex>u</tex>-е несовпадение при этом сдвиге, где <tex>1 < u < t</tex>, то есть <tex>p-i</tex> = <tex>pm[i-rpng|450px][u]</tex>.
Вспомним, что нас интересует, совпадает ли символ текста в позиции <tex>p</tex> с соответствующими символом образца, когда <tex>x[1]</tex> совмещен с <tex>y[i+1]</tex>, то есть верно ли, что <tex>y[p] = x[p-i]</tex>. Рассмотрим этот вопрос при разных комбинациях указанных выше условий.
'''Случай 1. : !A and !B:''' То есть, <tex>y[p] = x[p-r]</tex> и <tex>x[p-r] = x[p-i]</tex>, откуда <tex>y[p] = x[p-i]</tex>. Нет необходимости сравнивать символ текста с символом шаблонаобразца, так как ясно, что в этой позиции они совпадают.
'''Случай 2. : (A and !B) or (!A and B):''' В любом случае <tex>y[p] \neq x[p-i]</tex> (если лишь ''условие <tex>A</tex> '' истинно, то <tex>y[p] \neq x[p-r]</tex> и <tex>x[p-r] = x[p-i]</tex>, откуда <tex>y[p] \neq x[p-i]</tex>, с другой стороны, если выполнено только ''условие <tex>B</tex>'', то <tex>y[p] = x[p-r]</tex> и <tex>x[p-r] \neq x[p-i]</tex>, и опять, <tex>y[p] \neq x[p-i]</tex>). Как и в предыдущем случае, нет необходимости сравнивать символ текста с символом шаблонаобразца, так как известно, что они не совпадают.
'''Случай 3. : A and B:''' В этом случае мы ничего не можем сказать о том, совпадают ли символы <tex>y[p]</tex> и <tex>x[p-i]</tex>, поэтому их надо сравнить.
Возвращаемся к процедуре <tex>\mathrm{merge}</tex>. В ''случае 2'', или если в ''случае 3 '' выявлено несовпадение символов, необходимо увеличить количество несовпадений символов <tex>b</tex> на единицу и обновить <tex>tm[i][b]</tex>. Соответствующими значениями таблицы для <tex>\mathrm{merge}</tex> являются <tex>tm[i-r][1...t]</tex> и <tex>tm[r][q...k+1]</tex>. Переменные <tex>u</tex> и <tex>v</tex> в начале устанавливаются равными индексам первых элементов этих двух массововмассивов, соответственно, и последовательно увеличиваются.
Условия окончания работы процедуры следующие:
* Eсли Если <tex>b = k+1</tex>, то для случая, когда шаблон образец расположен относительно текста так, что <tex>x[1]</tex> совмещен с <tex>y[i+1]</tex>, обнаружено <tex>k+1</tex> несовпадение, поэтому из процедуры можно выйти.
* Bспомним, что самая правая из интересующих нас позиций в <tex>\mathrm{merge}</tex>, а именно, <tex>j</tex>, равна <tex>r+tm[r][k+1]</tex>, если <tex>v = k+2</tex>, поэтому <tex>tm[r][k+1]</tex> будет уже использовано для предыдущего значения <tex>v</tex>, а именно, <tex>v = k+1</tex>, и поэтому позиция <tex>j</tex> должна быть пропущена. Следовательно, в этом случае также можно выйти из процедуры.
* Процедуру можно прервать, если <tex>i+pm[i-r][u] > j</tex> и <tex>tm[r][v] = m+1</tex>. Если выполняется вторая часть этого условия, то <tex>r+tm[r][v]</tex> равняется <tex>j</tex>, и соответствует суммам для последующих значений <tex>v</tex> вплоть до <tex>k+1</tex>. В этом случае процедура может быть прервана, если выполняется также первая часть приведенного условия, так как она указывает, что позиция текста <tex>j</tex> фактически пропущена.
Остается показать, что число позиций несовпадений в таблице несовпадений шаблона образца достаточно для того, чтобы <tex>\mathrm{merge}</tex> нашла все, или, если их больше <tex>k+1</tex>, первые <tex>k+1</tex> несовпадений для <tex>y[i+1...j]</tex>. Это можно показать следующим образом. ''Условие A '' выполняется не больше чем для <tex>k+1</tex> позиции текста в диапазоне <tex>y[i+1...j]</tex>. ''Условие B '' выполняется для некоторого неизвестного числа позиций в этом же интервале. Строка <tex>i-r</tex> в таблице несовпадений шаблонаобразца, <tex>tm[i-r][1...2k+1]</tex>, содержит не больше чем <tex>2k+1</tex> позиций несовпадений между двумя копиями шаблонаобразца, с соответствующим сдвигом <tex>i-r</tex>. Если <tex>pm[i-r][2k+1] > j - i</tex>, то таблица содержит все позиции несовпадения шаблона образца самим с собой, у которых ''условие B '' выполняется для позиций текста в интервале <tex>y[i+1...j]</tex>. С другой стороны, если <tex>pm[i-r][2k+1] < j-i</tex>, то таблица может дать <tex>2k+1</tex> позиций текста в диапазоне <tex>y[i+1][...j-1]</tex>, для которых выполняется ''условие B''. Поскольку <tex>j = r+tm[r][k+1]</tex>, в диапазоне <tex>y[i+1][...j-1]</tex> имеется до <tex>k</tex> позиций текста, для которых выполняется ''условие A''. Таким образом, в худшем случае может быть <tex>k</tex> позиций, для которых имеет место ''случай 3'', и которые требуется сравнить напрямую. Остается по крайней мере <tex>k+1</tex> позиций, удовлетворяющих ''условию B'', но не ''условию A '' (''случай 2''), что является достаточным, чтобы заключить, что для данного положения шаблона образца относительно текста имеется не меньше <tex>k+1</tex> несовпадений между текстом и шаблономобразцом.
{| border="0"
|align="left" colspan="4"|
<font size=2>
'''int''' merge(i: '''int''', r: '''int''', j, b: '''int''') u = 1 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) v++ '''else ''' '''if ''' i + pm[i - r][u] < r + tm[r, ][v] <font color=green> // Случай 2, условие B</font> b++ tm[i][b] = pm[i - r][u] u++ '''else ''' // Случай 3 (?//todo) I '''if''' i + PMpm[I i - R, Ur][u] = R r + TMtm[R, Vr][v]<font color=green>// Случай 3 </font> '''if ''' x[ pm[i-r][u] ] != <tex>\neq</tex> y[ i+pm[i-r][u] ] b++ tm[i][b] = pm[i - r][u] u++ v++ '''return''' b
</font>
|}
===Построение pm===
Теперь осталось только обратиться к вычислению таблицы несовпадений шаблона образца на стадии предварительных вычислений. Не теряя общности, можно предположить, что <tex>m</tex> является некоторой степенью <tex>2</tex>. В алгоритме предварительной обработки используется разбиение множества <tex>{1, 2, ... , m-1}</tex> из <tex>m-1</tex> строк <tex>pm</tex> на следующие <tex>\log m</tex> подмножеств:
<tex>\{1\}, \{2, 3\}, \{4, 5, 6, 7\}, ... , \{m/2, ... , m-1\}</tex>
Алгоритм состоит из <tex>\log m</tex> этапов. На этапе <tex>s</tex>, где <tex>1 < \leqslant s < \log m</tex>, вычисляются строки <tex>pm</tex> в множестве <tex>s</tex>, где множество <tex>s</tex> {{---}} это <tex>\{2s2^{s-1}, ... , 2s2^{s}-1\}</tex>.
Метод, используемый для вычисления этой таблицы, основан на методе, используемом на стадии анализа текста. Рассмотрим алгоритм для этапа <tex>s</tex>. На стадии <tex>s</tex> входами для алгоритма анализа образца являются подстроки образца <tex>x[1...m-2^{s-1}]</tex> и <tex>x[2^{s-1}+1...m]</tex>, которые трактуются здесь, соответственно, как образец и текст, и массив <tex>pm[1...2^({s-1)}-1][1...\min\{2^{\log(m)-s}4k+1, m-2^{s-1}\}]</tex>, содержащий выходы предыдущих <tex>l s - 1</tex> стадий. (Число элементов в строках подмассива будет объяснено позже). Выходы стадии <tex>s</tex> вводятся в <tex>pm<//todotex>. За исключением стадии <tex>\log m</tex>, на которой находят до <tex>2k+1</tex> несовпадений, на стадии <tex>s</tex> для каждой строки <tex>pm</tex> требуется найти до <tex>\min\{2^{\log(m)-s}2k+1, m-2^{s}\}</tex> несовпадений, а не до <tex>k+1</tex>, как в алгоритме анализа текста.
{| border="0"
|align="left" colspan="4"|
<font size=2>
'''void''' precalcPm() pm[<tex>2^(h{s-1)}</tex>...<tex>2^h{s} -1</tex>][1...min({<tex>2^{\log(m-1)}2k-1</tex>, <tex>m-2^(h)){s}</tex>}] = m+1 r = <tex>2^(h{s-1)}</tex> j = <tex>2^(h{s-1)}</tex> '''for ''' i = <tex>2^(h{s-1) }</tex> to <tex>2^h {s} - 1</tex> b = 0 '''if ''' i < j b = merge(Ii, Rr, J, Bj) '''if ''' b < min({<tex>2^{\log(m-1)}2k-1, m-2^(h)){s} </tex>} r = i extend(i, j, b)
</font>
|}
===Оценка работысложности===
Теперь исследуем затраты времени на анализ текста. Если исключить вызовы процедур <tex>\mathrm{merge}</tex> и <tex>\mathrm{extend}</tex>, каждая из <tex>n-m+1</tex> итераций цикла анализа текста выполняется за фиксированное время, что дает в общей сложности время <tex>O(n)</tex>. Общее число операций, выполняемых процедурой <tex>\mathrm{extend}</tex> во время вызовов равно <tex>O(n)</tex>, так как она проверяет каждый символ текста не больше одного раза. Процедура <tex>\mathrm{merge}</tex> при каждом вызове обрабатывает вектора массив <tex>pm[i-r][1...2k+1]</tex> и <tex>tm[r][1...k+1]</tex>, которые в сумме имеют <tex>3k+2</tex> элементов. Время работы <tex>\mathrm{merge}</tex> можно рассчитать, соотнеся операции с фиксированным временем с каждым из этих входов, что дает время счета для каждого вызова, равное <tex>O(k)</tex>. Таким образом, можно видеть, что общее время анализа текста составляет <tex>O(nk)</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^{ls-1}(2k2^{\log (m) -s)}))</tex> = <tex>O(km)</tex>. Проведя суммирование по всем стадиям, получаем общее время счета <tex>O</tex> <tex>\displaystyle \left(\sum_{i=1}^{\log m} km\right) = O(km \log m)<//todo)tex>. Таким образом, общие затраты времени, включающие предварительную обработку шаблона образца и анализ текста, равны <tex>O(k(n + m \log m))</tex>.
==Пример==
Пусть <tex>x = "tram"</tex>, <tex>y = "thetrippedtrap"</tex>, <tex>k = 2</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
| '''2''' || 1 || 2 || 3 || tram || etri
|-
| '''3''' || 3 || 4 || style="background:#FFCC00b1b1ff"| 5 || '''tr'''am || '''tr'''ip
|-
| '''4''' || 1 || 2 || 3 || tram || ripp
| '''9''' || 1 || 2 || 3 || tram || dtra
|-
| '''10''' || 4 || style="background:#FFCC00b1b1ff"| 5 || style="background:#FFCC00b1b1ff"| 5 || '''tra'''m || '''tra'''p
|}
{| class="wikitable" cellpadding="4" border="1" style="border-collapse: collapse; text-align: center;"
|-
| tm 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
| '''3''' || 1 || 5 || 5 || 5 || 5 || t || m
|}
 
==См. также==
* [[Алгоритм Бойера-Мура]]
* [[Алгоритм Кнута-Морриса-Пратта]]
 
==Источники информации==
* [http://algolist.manual.ru/search/fsearch/k_nesovp.php Алгоритм Ландау-Вишкина {{---}} k несовпадений]
 
 
[[Категория: Алгоритмы и структуры данных]]
[[Категория: Поиск подстроки в строке]]
[[Категория: Нечёткий поиск]]
1632
правки

Навигация