Possível melhoria de Damerau-Levenshtein?


9

Eu recentemente implementei o algoritmo de distância Damerau-Levenshtein a partir do pseudocódigo na Wikipedia. Eu não poderia encontrar qualquer explicação sobre exatamente como ele funciona eo pseudocódigo usa nomes de variáveis completamente uninformative como DA, DB, i1, e j1que deixou-me coçar a cabeça.

Aqui está minha implementação em Python: https://gist.github.com/badocelot/5327337

A implementação do Python me ajudou a percorrer o programa e descobrir o que estava acontecendo, renomeando as variáveis ​​para nomes mais úteis. Eu estava familiarizado o suficiente com a abordagem de Wagner-Fischer para calcular a distância de Levenshtein e tinha um quadro de referência.

Correndo o risco de ser excessivamente longo, eis como eu entendo Damerau-Levenshtein:

As variáveis ​​misteriosas:

  • DA( last_rowno meu código) é um tipo de mapa que contém a última linha em que cada elemento foi visto; no meu código é um dicionário Python real
  • DB( last_match_col) mantém a última coluna em que a letra bcorresponde à letra ada linha atual
  • i1( last_matching_row) é o número da linha da DAletra atual emb
  • j1é apenas uma cópia do valor de DB/ last_match_colantes de ser potencialmente atualizado; no meu código acabei de me mudar para onde last_match_colé atualizado e eliminado essa variável

O custo de transposição:

H[i1][j1] + (i-i1-1) + 1 + (j-j1-1)

está calculando o custo de trocar o caractere atual bpelo último caractere bconhecido por a(a última correspondência), tratando todos os caracteres intermediários como adições ou exclusões.

Componentes do custo:

  • H[i1][j1] reverte o custo base para o ponto nos cálculos anteriores à transposição, pois encontrar uma transposição invalida trabalhos anteriores
  • (i-i1-1) é a distância entre a linha atual e a última linha correspondente ao caractere atual, que é o número de exclusões que seriam necessárias
  • (j-j1-1) é a distância entre a coluna atual e a última coluna com uma correspondência, que é o número de adições
  • O extra + 1é apenas o custo da própria transposição

Se essa análise estiver incorreta, eu adoraria saber onde errei. Como eu disse, não consegui encontrar nenhuma explicação detalhada de como o algoritmo funciona online.

Versão melhorada?

Tendo descoberto isso, no entanto, ocorreu-me que, calculando o custo de ambas as adições e exclusões entre as letras transpostas parecia falho: uma adição e uma eliminação é equivalente a uma substituição, que isso não está verificando.

Se tudo estiver correto, a solução deve ser trivial: o custo das letras entre as letras transpostas deve ser o mais alto das adições e exclusões: converta o maior número possível de substituições e adicione quaisquer adições ou exclusões restantes.

Portanto, o custo seria:

H[i1][j1] + max((i-i1-1), (j-j1-1)) + 1

Aqui está o meu código para esta versão: https://gist.github.com/badocelot/5327427

De alguns testes simples, isso parece correto. Por exemplo, "abcdef" -> "abcfad" fornece uma distância de edição de 2 (transponha "d" e "f", altere "e" para "a"), enquanto o algoritmo original fornece uma distância de 3 (três últimos) letras são substituições ou 1 transposição + 1 adição + 1 exclusão).

Agora, não posso ser a primeira pessoa a pensar nisso. Então, por que eu não o encontrei? Eu apenas não procurei por tempo suficiente? Ou existe alguma falha sutil que impede que isso realmente funcione?


Eu decidi escrever um post explicando DL em detalhes: scarcitycomputing.blogspot.com/2013/04/...
James Jensen

Respostas:


3

Eu tive que procurar a distância Damerau-Levenshtein na wikipedia, então me perdoe se isso estiver errado. Mas parece que só permite transpor cartas adjacentes e não arbitrárias. Portanto, seu exemplo "abcdef" -> "abcfad" com transposição de d e f não funciona. Parece-me que você modificou a definição do algoritmo e não está mais calculando a distância Damerau-Levenshtein.


Hmm, entendo o que você quer dizer. O DL permite transposições antes de adições ou após exclusões. Se ambos ocorreram, não é realmente uma transposição adjacente; portanto, os disparos de custo e o custo de transposição não serão escolhidos como o novo custo. Parecia que estava lidando com os dois porque os evita através de um efeito colateral da minimização de custos.
James Jensen
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.