Функция Левенштейна

advertisement
Функция Левенштейна
Насонов Денис
Данная статья достаточно подробно рассматривает задачу неточного совпадения 2-х
строк, обычно решаемую с помощью динамического программирования, с использованием
меры похожести, известной, как функция Левенштейна1.
В жизни нередко требуется найти различие, или расстояние между двумя цепочками
символов. Наиболее распространенными примерами могут служить операции в текстовых
базах данных,
в эволюционных, структуральных и функциональных исследованиях
биологических строк, в методах проверки правописания и т. д. Так что же такое неточное
совпадение строк, или редакционное расстояние?
формализации
данного
понятия.
Самый
Существует несколько способов
распространенный
из
них
основан
на
преобразованиях одной строки в другую серией операций редактирования, выполняемых
над отдельными символами. Существуют 3 основные редакционные операции: удаление
символа из строки, вставка символа в строку, замена символа в строке. Введем некоторые
фундаментальные понятия.
Определение: Оптимальным предписанием будем называть минимальное число
операций, необходимых для преобразования строки S1 (Source) в строку S2 (Target).
Определение: Редакционное предписание между 2-мя строками определяется
как минимальное число редакционных операций, т.е. вставок, удалений, замен,
необходимых для преобразования одной строки (S1) в другую (S2).
Замечание: нужно отметить, что оптимальных (в том числе и редакционных) предписаний
может быть больше одного.
Прежде, чем приступить к формальному описанию и реализации задачи, рассмотрим
некоторые области применения нашей функции.
1
Владимир Иосифович Левенштейн (родился в 1935 году) – видный российский ученый, доктор физикоматематических наук, окончил МГУ им. М.В. Ломоносова, Механико-математический факультет. В настоящее
время работает ведущим научным сотрудником в Институте Прикладной Математики им. М.В. Келдыша.
Благодаря введенному им в 1965 году понятию дистанции редактирования, названной его именем, доктор
Левенштейн обрёл всемирную известность.
________________________________________________________________________________
© Насонов Денис
© http://rain.ifmo.ru/cat
1
Правописание слов. Расстояние редактирования является базовым параметром,
активно использующимся в различных грамматических приложениях; таких, к примеру,
как
правописание в MS Office, или в других подобных программных продуктах. Метод
работы данного сервиса можно представить себе, рассмотрев следующий пример:
Расстояние
редактирования
Источник
Эталон
Самовар
самовар
Самавар
Самовар
0 (строки
идентичны)
1
Самимавр
Самовар
4
Здесь, при проверке на правильность написания некорректно введенного слова,
служба осуществляет поиск по базовому словарю на неточное совпадение с «эталонами».
Функция Левенштейна же играет роль фильтра, заведомо отбрасывающего неприемлемые
варианты (у которых значение функции больше некоторой заданной константы).
Похожий алгоритм применяется и в распознавании речи, и в молекулярной
биологии (работа со структурой ДНК), и в
“Fuzzy search”, используемом интернет-
поисковыми системами (как более гибкий поиск). Схема проста: web-сервер осуществляет
точный поиск по заданному выражению и, в случае неудовлетворительного результата,
поиск повторяется с использованием неточного совпадения. Однако значительным
минусом такого поиска является время его выполнения.
Иногда,
для
большей
наглядности,
в
редакционном
предписании
используют
обозначения следующего вида:
I – insert
D – delete
R – replace
M – match
Тогда для 2-х строк “ANALYSES” и “ANNULUSE” можно построить следующую таблицу
преобразований:
M
I
A
A
N
M
R
M
R
M
M
D
N
A
L
Y
S
E
S
N
U
L
U
S
E
В итоге, можно не только подсчитать функцию Левенштейна, но также показать одно
из преобразований.
________________________________________________________________________________
© Насонов Денис
© http://rain.ifmo.ru/cat
2
Задача о редакционном расстоянии
Теперь рассмотрим задачу вычисления функции Левенштейна и ее редакционного
предписания
с
помощью
динамического
программирования.
Основы
динамического
программирования, вероятно, хорошо известны читателю. Поэтому мы рассмотрим его
специфическое приложение к задаче о редакционном расстоянии.
Определение: Для двух строк S1 и S2 значение D(i, j) определим, как редакционное
расстояние между S1[1..i] и S2[1..j].
Т.е. D(i, j) определяет минимальное число
операций, необходимых для преобразо-
вания первых i символов S1, в первые j символов S2. Но чтобы найти D(i, j), необходимо
решить более общую задачу, а именно: вычислить D(i`, j`) для всех комбинаций i` и j`,
где i` меняется от 0 до i, а j` от 0 до j, т. е. применить стандартный метод динамического
программирования, содержащий три основных компоненты: рекуррентное соотношение,
табличная форма вычислений и обратный проход. Поясним каждую компоненту.
Рекуррентное соотношение
Рекуррентное соотношение задает рекурсивное отношение между значением
D(i, j)
для положительных i и j и значениями D с индексными парами, меньшими i, j. Когда
меньших индексов нет, значение D(i, j)
должно получаться явно из условий, которые
будем называть базой, т. е.:
D(i, 0) = i, D(0, j) = j.
Очевидно, что выше написанные выражения логически верны. Действительно, в
первом случае, единственным способом получения из i символов S1
0 символов S2
является удаление этих i символов, аналогично и для D(0, j) только не удаление, а
вставка. Теперь убедимся в корректности всей рекурсии благодаря следующим двум
леммам, использующим концепцию редакционного предписания.
Лемма 1. Значение D(i, j) должно совпадать с D(i-1, j) + 1 , D(i, j-1) + 1 или D(i-1, j1) + price(i, j), где price(i, j) = 0, если S1(i) = S2(j), и равно
1 - в противном случае.
Других возможностей нет.
________________________________________________________________________________
© Насонов Денис
© http://rain.ifmo.ru/cat
3
Доказательство: Рассмотрим редакционное предписание для преобразования S1[1..i] в
S2[1..j] с минимальным числом редакционных операций и проанализируем последний
символ этого предписания. По определению, он должен быть равен I, D, R или М.
Рассмотрим каждый случай по порядку.
Если это операция I, то на последнем шаге была произведена вставка символа S2(j) в
конец (преобразуемой) первой строки. Но тогда
символы в предписании до этого I
должны обеспечивать минимальное число операций, преобразующих S1[1..i] в S2[1..j-1]
(иначе такое
представление S1[1..i] в S2[1..j] не являлось бы оптимальным). Однако,
последнее преобразование требует D(i, j-1) редакционных операций и, если, на данном
шаге, конечный символ в предписании равен I, то D(i, j) =D(i, j-1) + 1.
Аналогично,
если
конечный
символ
в
предписании
равен
D,
то
последняя
редакционная операция была удалением S1(i), а, следовательно, символы в предписании,
влево от этого D, должны задавать минимальное число редакционных операций для
преобразования S1[1..i-1] в S2[1..j]. По определению, это последнее преобразование
требует D(i–1, j) редакционных операций. Таким образом, если последний символ в
предписании равен D, то D(i, j) = D(i-1, j) + 1.
Теперь,
пусть
последний
символ
в
предписании
равен
R,
тогда
последняя
редакционная операция заменяет S1(i) на S2(j), а символы, влево от R, определяют
минимальное число редакционных операций для преобразования S1[1 ..i-1] в S2[1..j-1]. В
этом случае D(i, j) = D(i-1, j-1) + 1. Наконец, по аналогичным причинам, если последний
символ в предписании равен М, то S1(i) = S2(j) и D(i, j) =D(i-1, j-1). Используя введенную
переменную price(i, j), мы можем соединить два последних случая в один, т. е. для М
price(i, j) = 0, и тогда (для M, R): D(i, j) = D(i-1, j-1) + price(i, j).
Теперь докажем не менее важную лемму, которая также поможет в доказательстве
основной теоремы.
Лемма 2.
D(i, j) ≤ min {D(i-1, j) + 1 , D(i, j-1) + 1, D(i-1, j-1) + price(i, j)}.
Доказательство:
Рассуждения
в
доказательстве
будут
очень
похожими
на
предложенные рассуждения в предыдущей лемме, но их цель несколько отлична. Сейчас
мы намерены конструктивно показать существование преобразований, на которых
достигается каждое из трех значений, выписанных в неравенстве. И так как каждое из
трех значений достижимо, их минимум также будет достижим.
Во-первых,
редакционных
можно
преобразовать
операций.
Нужно
S1[1..i]
просто
в
S2[1..j]
преобразовать
ровно
за
S1[1..i]
в
D(i,
j-1)
+
S2[1..j-1]
1
за
минимальное число операций и использовать еще одну операцию, чтобы вставить символ
S2(j) в конце. По определению, число редакционных операций в этом конкретном способе
________________________________________________________________________________
© Насонов Денис
© http://rain.ifmo.ru/cat
4
преобразования S1 в S2 равно D(i, j-1) + 1. Далее, можно преобразовать S1[1..i] в
S2[1..j] ровно за D(i-1, j) + 1 операций: преобразовать S1[1..i-1]
в S2[1..j]
за
наименьшее число операций и затем удалить S1(i), что и даст в итоге D(i-1, j-1) + 1.
Очевидно, какие преобразования необходимы для D(i-1, j-1) + price(i, j) операций.
Теорема.
Рекуррентное отношение задано корректно и D(i, j) = min {D(i-1, j) + 1,
D(i, j-1) + 1, D(i-1, j-1) + price(i, j)}, когда i и j > 0.
Доказательство: Доказательство тривиально следует из лемм 1 и 2.
Табличная форма вычислений
Теперь поговорим об эффективном вычислении самого значения D(m, n). Естественно,
можно
напрямую
запрограммировать
рекуррентное
соотношение
в
виде
самой
процедурной рекурсии и получить необходимый результат, так называемым, нисходящим
методом.
Однако, при достаточно больших значениях m, n число рекурсивных вызовов будет
расти экспоненциально, хотя различных комбинаций существует только (n+1)*(m+1). Все
дело в
принципиальном подходе, а именно: отличия нисходящего и восходящего
методов.
При восходящих расчетах, на каждом шаге происходит вычисление очередного
значения таблицы, получаемого исключительно из уже заполненных ячеек. Такой
нехитрый способ требует всего (n+1)*(m+1) шагов и будет достаточно эффективным.
Пример заполнения таблицы:
начальный этап
промежуточные расчеты
окончательное состояние
________________________________________________________________________________
© Насонов Денис
© http://rain.ifmo.ru/cat
5
Вот одна из реализаций нашей задачи: псевдо-алгоритм с краткими пояснениями, как
видно, время его работы O(n*m):
1. n = Length(S);
2. m = Length(T);
3. если n = 0, то расстояние редактирования равно m и завершается работа алгоритма;
4. если m = 0, то расстояние редактирования равно n и завершается работа алгоритма;
5. создаем массив mtr размером [m+1][n+1];
6. инициализируем первую строку и столбец массива mtr:
for (i = 0; i ≤ n; i++) mtr[0][i] = i;
for (i = 1; i ≤ m; i++) mtr[i][0] = i;
7. само вычисление расстояния редактирования:
for (i = 1; i ≤ n; i++){
s = S[i];
for (j = 1; j ≤ m; j++){
t = T[j];
price = (t == s) ? 0 : 1;
mtr[j][i] = Min (mtr[j][i-1] + 1, mtr[j-1][i] + 1, mtr[j-1][i-1] + price);
}
}
8. расстояние редактирования равно ячейке массива mtr[m][n].
Осталось рассмотреть последнюю компоненту ― обратный проход.
Обратный проход
Нам необходимо определить: каким образом, после вычисления редакционного
расстояния, можно найти соответствующее оптимальное предписание? Простейший путь
заключается в том, чтобы, по мере вычисления значений в клетках, хранить указатель на
ту ячейку, откуда данное значение было получено.
Если рассматривать подробней, то при вычислении значения в клетке (i, j) необходимо
установить в ней указатель на (i, j-1) ячейку, при D(i, j) = D(i, j-1) + 1 и D(i, j) = D(i-1, j)
+ 1, и указатель на (i-1, j-1) ячейку, при D(i, j) = D(i-1, j-1)+ price(i, j). Это правило
применяется также к клеткам в нулевой строке и нулевом столбце. Таким образом, по
завершению заполнения таблицы, можно построить одно из оптимальных предписаний,
просто пробегая по указателям, начиная с ячейки (m, n).
________________________________________________________________________________
© Насонов Денис
© http://rain.ifmo.ru/cat
6
Дополнительные сведения
Операционно-взвешенное редакционное расстояние
Неким
обобщением функции Левенштейна является возможность использования
произвольной весовой стоимости, приписываемой каждой редакционной операции, в том
числе и совпадению. Таким образом, любое включение или удаление имеет вес d, замена
имеет вес r, а совпадение – e. При таких условиях определение редакционного
расстояния
немного
изменяется.
операционно-взвешенном
При
редакционном
произвольных
расстоянии
весах
операций
называется
задачей
задача
о
об
поиске
редакционного предписания, которое переводит строку S1 в S2 с минимальным полным
весом операций. Определенно, понятно тогда, как выглядит сама рекуррентная формула.
Можно отметить также существование такого понятия, как алфавитно-взвешенное
редакционное расстояние.
Его особенность заключается в различном весовом
значении функции замены. К примеру, вес можно
символов, упорядоченных в лексикографическом
задать как разность номеров двух
порядке. Такая конструкция часто
применяется в молекулярной биологии, в частности, в исследованиях цепочек ДНК.
Источники
1. Гасфилд Д. Строки, деревья и последовательности в алгоритмах: Информатика и вычислительная
биология / Пер. с англ. И.В. Романовского. ― СПб.: Невский Диалект, 2003. ― 654 с.
2. Романовский И. В. Дискретный анализ: Учебное пособие для студентов специализирующихся по
прикладной математике и информатике / 3-е изд., перераб. и доп. ― СПб.: Невский Диалект, 2003.
― 320 с.
3. Функция Левенштейна (http://aforge.ibd.lv/)
________________________________________________________________________________
© Насонов Денис
© http://rain.ifmo.ru/cat
7
Download