Lição
A teoria — Visualizador da Distância de Levenshtein
A distância de Levenshtein entre duas cadeias é o menor número de edições de um único carácter que transforma uma na outra, sendo uma edição uma inserção, uma eliminação ou uma substituição. É um mínimo sobre todas as maneiras possíveis de o fazer, e é isso que a torna difícil de avaliar a olho e fácil de calcular com uma grelha: existe um número astronómico de sequências de edição, e este procedimento encontra a mais curta sem listar nenhuma.
O que significa cada símbolo
m, n- os comprimentos das duas cadeias, A e B.
D(i, j)- a forma mais barata de transformar os primeiros i caracteres de A nos primeiros j caracteres de B. Uma célula da tabela desta página.
[aᵢ ≠ bⱼ]- vale 1 quando esses dois caracteres diferem e 0 quando coincidem — o preço da substituição, que desaparece se não houver nada a substituir.
d- a resposta,
D(m, n): a célula do canto inferior direito.
De onde vem a fórmula
- Decida o que significa uma célula antes de preencher qualquer uma. Seja
D(i, j)o número mínimo de edições que transforma os primeirosicaracteres de A nos primeirosjde B. O número que procura éD(m, n), e qualquer outra célula é uma versão menor da mesma pergunta. - As margens não exigem raciocínio. Para construir os primeiros
jcaracteres de B a partir do nada é preciso fazerjinserções, logoD(0, j) = j. Para reduzir a nada os primeiroside A é preciso fazerieliminações, logoD(i, 0) = i. É a linha de cima e a coluna da esquerda da grelha, e é por isso que se limitam a contar. - Agora o passo que faz todo o trabalho. Pegue em qualquer sequência óptima para
D(i, j)e olhe apenas para o seu último movimento. Há três possibilidades e mais nenhuma: eliminouaᵢ, deixando a tarefaD(i−1, j); inseriubⱼ, deixandoD(i, j−1); ou emparelhouaᵢcombⱼ, deixandoD(i−1, j−1). Cada uma delas é uma célula que já preencheu. - Portanto a célula é a mais barata das três:
D(i, j) = min( D(i−1, j) + 1, D(i, j−1) + 1, D(i−1, j−1) + [aᵢ ≠ bⱼ] ). Preencha a grelha da esquerda para a direita e de cima para baixo, e ao chegar a qualquer célula as suas três vizinhas já são conhecidas. É todo o algoritmo —m × ncélulas, três comparações cada.
Como ler o que vê
A grelha desta página é essa tabela. As linhas são A, as colunas são B, e a linha e a coluna extra no canto superior esquerdo são os prefixos vazios do passo 2 — daí contarem 0, 1, 2, 3. O sombreado de cada célula é o seu valor: o corredor diagonal pálido é onde as duas cadeias ainda coincidem barato. Passe o rato ou toque em qualquer célula e o painel por baixo detalha o passo 3 para essa célula — os três candidatos, cada um com a sua aritmética, e o vencedor destacado. A linha colorida é uma rota óptima traçada para trás a partir do canto inferior direito, e a faixa de alinhamento por baixo é essa mesma rota escrita em caracteres.
- Pressupõe
- Cada edição custa exactamente 1 e os caracteres são comparados por igualdade exacta — sem uniformização de maiúsculas, sem normalização Unicode e sem qualquer noção de que caracteres se parecem. Vêem-se aqui duas consequências. O que se conta aqui são unidades de código UTF-16, não aquilo a que chamaria letras: escreva um único emoji numa caixa e a tabela é 3 × 1, porque um emoji são duas unidades e eliminá-lo custa 2. E
cafécom umépré-composto contracaféescrito comoemais um acento combinante dá distância 2, embora os dois pareçam idênticos no ecrã. - Falha quando
- A grelha tem
m × ncélulas, pelo que o trabalho cresce com o produto dos comprimentos. Isso serve para duas palavras e é inviável para uma consulta contra um dicionário de um milhão de entradas, que são um milhão de grelhas. A resposta natural seria um algoritmo mais esperto, e a surpresa é que praticamente não existe: Backurs e Indyk mostraram em 2015 que uma distância de edição fortemente subquadrática refutaria a hipótese do tempo exponencial forte. Os correctores ortográficos reais não batem esse limite, contornam-no — parando assim que a distância excede um pequeno limiar, ou indexando de modo que quase nenhum candidato chegue a ser comparado.
Problema resolvido na íntegra
-
A sequência de edições de menor custo para transformar kitten em sitting 5 passos
Transforme kitten em sitting. Encontre a sequência de edições mais económica e prove que não existe nenhuma mais económica — depois, calcule quanto isto custa quando a segunda palavra é um dicionário inteiro.
-
A relação de recorrência é todo o algoritmo. Cada célula calcula quanto custa chegar aqui eliminando, inserindo ou alinhando os dois carateres atuais — sendo a última opção gratuita quando eles coincidem. Uma célula necessita apenas dos três vizinhos acima e à sua esquerda, pelo que um único varrimento da esquerda para a direita preenche a tabela.
-
Antes de preencher seja o que for, limite o intervalo da resposta. Os comprimentos diferem em um, pelo que pelo menos uma inserção é inevitável; e reescrever a palavra por completo custa 7. A resposta encontra-se no meio, o que elimina logo a maioria dos palpites.
-
Três edições resolvem o problema: substituir k → s, substituir e → i, inserir g. Cada uma é uma única edição válida e a cadeia termina no alvo.
-
Apresentar três edições apenas prova que a distância é no máximo 3. A tabela prova que é exatamente 3, porque todos os percursos até ao canto inferior direito são pontuados e o mínimo é considerado em cada célula ao longo do caminho. Essa é a diferença entre encontrar uma resposta e saber que ela não pode ser superada.
-
O custo é de uma célula por par de carateres — 42 aqui, o que não é nada. Confrontado com um dicionário de 100 000 palavras com sete letras cada uma, são mais de quatro milhões de atualizações de células para uma única pesquisa.
Resposta
A ferramenta apresenta 3 e uma semelhança de 57,14%, que é 1 − 3/7: a distância normalizada pela palavra mais longa. Ambas provêm de uma tabela que pode preencher à mão num minuto. O que não se ajusta à escala é a tabela — o trabalho é Θ(mn), pelo que duplicar ambas as cadeias quadruplica-o, e todos os corretores ortográficos que já utilizou foram concebidos para evitar fazer isto. A solução não é uma tabela mais rápida. É o facto de a distância de Levenshtein satisfazer a desigualdade triangular, de modo que d(a, c) ≤ d(a, b) + d(b, c) permite a um índice provar que um candidato está demasiado distante sem nunca medir essa distância.
-
Referências (4)
- The theory section ends on why nobody has a much faster algorithm. This is the result that says they probably cannot have one: A. Backurs & P. Indyk, "Edit Distance Cannot Be Computed in Strongly Subquadratic Time (Unless SETH is False)." SIAM Journal on Computing 47(3), 1087–1097, 2018; first presented at STOC 2015.
- The grid this tool fills, and why filling each cell once is enough: R. A. Wagner & M. J. Fischer, "The String-to-String Correction Problem." Journal of the ACM 21(1), 168–173, 1974 — the dynamic-programming algorithm for the edit distance Levenshtein had defined in 1965.
- The fourth move in the Damerau cost model, and the survey of typing errors that argued for it: F. J. Damerau, "A technique for computer detection and correction of spelling errors." Communications of the ACM 7(3), 171–176, 1964.
- Insight block 3 ends on the problem of recovering the route without keeping the grid. This is the paper that solved it: D. S. Hirschberg, "A linear space algorithm for computing maximal common subsequences." Communications of the ACM 18(6), 341–343, 1975.