Недавно я реализовал алгоритм расстояния Дамерау-Левенштейна из псевдокода в Википедии. Я не мог найти никакого объяснения того , как именно она работает и псевдокод использует имена полностью неинформативные переменные , как DA, DB, i1, и j1что оставил меня почесал голову.
Вот моя реализация в Python: https://gist.github.com/badocelot/5327337
Реализация Python помогла мне пройтись по программе и выяснить, что происходит, переименовав переменные в более полезные имена. Я был достаточно знаком с подходом Вагнера-Фишера к вычислению расстояния Левенштейна, и у меня была система отсчета.
С риском быть слишком длинным, вот как я понимаю Дамерау-Левенштейна:
Тайные переменные:
DA(last_rowв моем коде) это своего рода карта, содержащая последнюю строку, на которой был замечен каждый элемент; в моем коде это фактический словарь PythonDB(last_match_col) содержит последний столбец, в котором букваbсоответствует букве вaтекущей строкеi1(last_matching_row) - номер строкиDAдля текущей буквы вbj1это просто копия значенияDB/last_match_colдо его потенциального обновления; в моем коде я только что переехал, гдеlast_match_colобновляется и исключается эта переменная
Стоимость перестановки:
H[i1][j1] + (i-i1-1) + 1 + (j-j1-1)
вычисляет стоимость замены текущего символа bна последний из bизвестных символов a(последнее совпадение), рассматривая все символы между ними как добавления или удаления.
Составляющие стоимости:
H[i1][j1]восстанавливает базовую стоимость до точки в расчетах до транспонирования, так как поиск транспозиции делает недействительной предыдущую работу(i-i1-1)это расстояние между текущей строкой и последней строкой, соответствующей текущему символу, которое является количеством удалений, которое потребуется(j-j1-1)это расстояние между текущим столбцом и последним столбцом с соответствием, которое является количеством добавлений- Дополнительным
+ 1является только стоимость самой транспозиции
Если этот анализ неверен, я хотел бы знать, где я ошибся. Как я уже сказал, я не мог найти какое - либо подробное объяснение того , как работает алгоритм онлайн.
Улучшенная версия?
Однако, выяснив это, меня поразило, что при расчете стоимости как добавлений, так и удалений между транспонированными буквами показалось ошибочным: одно добавление и одно удаление эквивалентны замене, которая не проверяется.
Если все правильно, решение должно быть тривиальным: стоимость букв между транспонированными буквами должна быть выше, чем у добавлений и удалений: конвертировать как можно больше в подстановки и добавлять любые оставшиеся добавления или удаления.
Так что стоимость будет:
H[i1][j1] + max((i-i1-1), (j-j1-1)) + 1
Вот мой код для этой версии: https://gist.github.com/badocelot/5327427
Из некоторых простых тестов это кажется правильным. Например, «abcdef» -> «abcfad» дает расстояние редактирования 2 (транспонировать «d» и «f», измените «e» на «a»), в то время как оригинальный алгоритм дает расстояние 3 (последние три буквы - это замены, или 1 транспонирование + 1 добавление + 1 удаление).
Теперь я не могу быть первым человеком, который подумал об этом. Итак, почему я не столкнулся с этим? Разве я не достаточно долго искал? Или есть какой-то тонкий недостаток, который мешает этому на самом деле работать?