Недавно я реализовал алгоритм расстояния Дамерау-Левенштейна из псевдокода в Википедии. Я не мог найти никакого объяснения того , как именно она работает и псевдокод использует имена полностью неинформативные переменные , как 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
для текущей буквы вb
j1
это просто копия значения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 удаление).
Теперь я не могу быть первым человеком, который подумал об этом. Итак, почему я не столкнулся с этим? Разве я не достаточно долго искал? Или есть какой-то тонкий недостаток, который мешает этому на самом деле работать?