Изменения

Перейти к: навигация, поиск
Формула: Цитирую: Так же очевидно то, что чтобы получить пустую строку из строки длиной <tex>i</tex>, нужно совершить <tex>i</tex> операций удаления
{{Определение
|id=levenstain_dist
|definition=
'''Расстояние Левенштейна''' (англ. ''Levenshtein distance'') (также '''редакционное расстояние''' или '''дистанция редактирования''') между двумя строками в теории информации и компьютерной лингвистике — это минимальное количество операций вставки одного символа, удаления одного символа и замены одного символа на другой, необходимых для превращения одной строки в другую.}}
* <tex>\rm{d}(S_1,S_2) = 0 \Leftrightarrow S_1 = S_2</tex>
где <tex>\rm{d}(S_1,S_2)</tex> — расстояние Левенштейна между строками <tex>S_1</tex> и <tex>S_2</tex>, а <tex>|S|</tex> — длина строки <tex>S</tex>.
 
Расстояние Левенштейна является [[Метрическое пространство|метрикой]].
Для того чтобы доказать это достаточно доказать что выполняется неравенство треугольника:
* <tex>\rm{d}(S_1,S_3) \leqslant \rm{d}(S_1,S_2) + \rm{d}(S_2,S_3)</tex>
 
Пусть <tex>\rm{d}(S_1,S_3) = x</tex>, <tex>\rm{d}(S_1,S_2) = y</tex>, <tex>\rm{d}(S_2,S_3) = z</tex>. <tex>x</tex> — кратчайшее редакционное расстояние от <tex>S_1</tex> до <tex>S_3</tex>, <tex>y</tex> — кратчайшее редакционное расстояние от <tex>S_1</tex> до <tex>S_2</tex>, а <tex>z</tex> — кратчайшее редакционное расстояние от <tex>S_2</tex> до <tex>S_3</tex>. <tex>y + z</tex> — какое-то расстояние от <tex>S_1</tex> до <tex>S_3</tex>. В других случаях <tex>\rm{d}(S_1,S_3) < \rm{d}(S_1,S_2) + \rm{d}(S_2,S_3)</tex>. Следовательно, выполняется неравенство треугольника.
== Разные цены операций ==
* <tex>w(a, \varepsilon)</tex> — цена удаления символа <tex>a</tex>
Для решения задачи о редакционном расстоянии, необходимо найти последовательность замен, минимизирующую суммарную цену. Расстояние Левенштейна является частным случаем этой задачи при* <tex>w(a, a)</tex> = <tex>0</tex>* <tex>w(a, b)</tex> = <tex>1</tex> при <tex>a\ne b</tex>* <tex>w(\varepsilon, b)</tex> = <tex>1</tex>* <tex>w(a, \varepsilon)</tex> = <tex>1</tex>
<tex>\varepsilon</tex> — пустая последовательность.
<tex>\ \rm{d}(S_1, S_2) = \rm{D}(M,N)</tex> , где
<tex>\rm{D}(i, j) = \left\{\begin{array}{llcl}0&&;&\ i = 0,\ j = 0\\i&* deleteCost&;&\ j = 0,\ i > 0\\j&* insertCost&;&\ i = 0,\ j > 0\\D(i - 1, j - 1)&&;&\ S_1[i] = S_2[j]\\\rmmin{(}\\\begin{minarray}({llcl}&D}(i, j - 1) + insertCost\\\rm{&D}(i - 1, j) + deleteCost&&\\&D(i - 1, j - 1) + replaceCost\\\end{array}&;&\ j > 0,\ i > 0,\ S_1[i] \ne S_2[j]\\\rm{D}(i - 1, j - 1) + replaceCost)\\ 
\end{array}\right.
</tex>,
<tex>\min(a, b, c)</tex> возвращает наименьший из аргументов.
=== Доказательство ===
Рассмотрим формулу более подробно. Здесь <tex>D(i, j)</tex> — расстояние между префиксами строк: первыми <tex>i</tex> символами строки <tex>S_1</tex> и первыми <tex>j</tex> символами строки <tex>S_2</tex>. Для нашей динамики должен выполняться [[Динамическое программирование|принцип оптимальности на префиксе]]. Очевидно, что редакционное расстояние между двумя пустыми строками равно нулю. Так же очевидно то, что чтобы получить пустую строку из строки длиной <tex>i</tex>, нужно совершить <tex>i</tex> операций удаления, а чтобы получить строку длиной <tex>j</tex> из пустой, нужно произвести <tex>j</tex> операций вставки. Осталось рассмотреть нетривиальный случай, когда обе строки непусты.
Для начала заметим, что в оптимальной последовательности операций, их можно произвольно менять местами. В самом деле, рассмотрим две последовательные операции:
Для нахождения кратчайшего расстояния необходимо вычислить матрицу <tex>D</tex>, используя [[#Формула|вышеприведённую формулу]]. Её можно вычислять как по строкам, так и по столбцам.
Псевдокод алгоритма, написанный при произвольных ценах замен, вставок и удалений (важно помнить, что элементы нумеруются с <tex>1</tex>):
 
Псевдокод ниже решает простой частный случай, когда вставка символа, удаление символа и замена одного символа на другой стоят одинаково для любых символов.
 
<code>
'''int''' '''levensteinInstruction'''('''String''' s1, '''String''' s2, '''int[]''' S2InsertCostInsertCost, '''int[]''' S1DeleteCostDeleteCost, '''int[]''' ReplaceCost):
D[0][0] = 0
'''fo'''r j = 1 '''to''' N
D[0][j] = D[0][j - 1] + S2InsertCost[j] InsertCost <font color=darkgreen>//S2InsertCost[j] - цена вставки символа S2[j]</font color=darkgreen>
'''for''' i = 1 '''to''' M
D[i][0] = D[i - 1][0] + S1DeleteCost[i] DeleteCost <font color=darkgreen>//S1DeleteCost[i] - цена удаления символа S1[i]</font color=darkgreen>
'''for''' j = 1 '''to''' N
'''if''' S1[i] != S2[j]
D[i][j] = min(D[i - 1][j] + S1DeleteCost[i]DeleteCost, D[i][j - 1] + S2InsertCost[j]InsertCost, D[i - 1][j - 1] + ReplaceCost[i][j]) <font color=darkgreen>//ReplaceCost[i][j] - цена замены символа S1[i] на символ S2[j]</font color=darkgreen>
'''else'''
D[i][j] = D[i - 1][j - 1]
=== Память ===
Алгоритм в виде, описанном выше, требует <tex>\Theta(M \cdot N)</tex> операций и такую же память, однако, если требуется только расстояние, легко уменьшить требуемую память до <tex>\Theta(\min(M,N))</tex>. Для этого надо учестьЗаметим, что после вычисления любой строки предыдущая строка больше не нужна. Более того, после для вычисления <tex>D([i, j)]</tex> не нужны также нам нужно только <tex>D([i-1]</tex>,0)поэтому будем вычислять <tex>D[i]</tex> в <tex>\dotsD[1]</tex> , а <tex>D([i-1,j-1)]</tex>. Поэтому алгоритм можно переписать какв <codetex> '''for''' i = 0 '''to''' M '''for''' j = 0 '''to''' N вычислить D[i0][j] '''if''' i </tex> 0 и j . Осталось только поменять местами <tex> 0 стереть D[i - 1][j - 1] '''return''' </tex> и <tex>D[M, N0]</codetex>.
=== Черновик ===
<code>
'''int''' '''levensteinInstruction'''('''int[]''' D): '''for''' i = 0 '''to''' M '''for''' j = 0 '''to''' N вычислить D[1][j] swap(D[0], D[1]) '''return''' D[0, ][N]
</code>
== Редакционное предписание ==
''Редакционным предписанием'Редакционное предписание' называется '' (англ. ''Editorial prescription'') — последовательность действий, необходимых для получения из первой строки второй кратчайшим образом. Обычно действия обозначаются так: '''D''' (англ. delete) — удалить, '''I''' (англ. insert) — вставить, '''R''' (англ. replace) — заменить, '''M''' (англ. match) — совпадение.
Например, для 2-х строк «hell123» и «hello214» можно построить следующую таблицу преобразований:
|h ||e||l ||l ||o ||2 ||1 ||4
|}
 
==См. также==
*[[Задача о расстоянии Дамерау-Левенштейна]]
== Источники информации ==
5
правок

Навигация