O problema se torna mais fácil se considerarmos exclusões longas e cópias de substring em vez de transposições. Suponha que estamos usando o algoritmo de programação dinâmica padrão para a computação editar distância, e que uma operação cara de comprimento aumenta a distância por um k + b , para algumas constantes a , b ≥ 0 . Essas constantes podem ser diferentes para exclusões longas e cópias de substring.ka k + ba , b ≥ 0
Uma exclusão longa é a exclusão de uma substring arbitrária de . É fácil apoiá-los, se os dividirmos em dois tipos de operações simples: excluir o primeiro caractere (custo a + b ) e estender a exclusão em um caractere (custo a ). Além da matriz padrão A , onde A [ i , j ] é a distância de edição entre os prefixos x [ 1 … i ] e y [ 1 … j ] , usamos outra matriz A dxa + bumaUMAA [ i , j ]x [ 1 ... i ]y[ 1 ... j ]UMAdpara armazenar a distância de edição, quando a última operação usada foi uma exclusão longa. Com essa matriz, só temos de olhar para , A [ i - 1 , j - 1 ] , A [ i , j - 1 ] e A d [ i - 1 , j ] ao calcular A [ i , j ] e A d [ iA [ i - 1 , j ]A [ i - 1 , j - 1 ]A [ i , j - 1 ]UMAd[ i - 1 , j ]A [ i , j ] , nos permitindo fazê-lo em O ( 1 ) tempo.Ad[i,j]O(1)
Cópia de subcadeia significa a inserção de uma subcadeia arbitrária de na cadeia editada. Assim como nas exclusões longas, dividimos a operação em duas operações simples: inserir o primeiro caractere e estender a inserção por um caractere. Também usamos a matriz A s para armazenar a distância de edição entre os prefixos, desde que a última operação usada seja a cópia de substring.xAs
Fazer isso de forma eficiente é mais complicado do que com exclusões longas, e não tenho certeza se podemos chegar ao tempo amortizado por célula. Construímos uma árvore de sufixos para x , que leva tempo O ( | x | ) , assumindo um alfabeto de tamanho constante. Armazenamos um ponteiro para o nó da árvore do sufixo atual em A s [ i , j - 1 ] , permitindo verificar em tempo constante, se podemos estender a inserção pelo caractere y [ j ] . Se isso for verdade, podemos calcular A [ iO(1)xO(|x|)As[i,j−1]y[j] e A s [ i , j ] em tempo constante.A[i,j]As[i,j]
Caso contrário, , em que z é a subcadeia inserida usada para calcular A s [ i , j - 1 ] , não é uma subcadeia de x . Usamos a árvore de sufixos para encontrar o sufixo mais longo z ′ de z , para o qual z ′ y [ j ] é uma subcadeia de x , em O ( | z | - | z ′ | ) . Para calcularzy[j]zAs[i,j−1]xz′zz′y[j]xO(|z|−|z′|) , agora precisamos observar as células A [ i , j - | z ′ | - 1 ] a A [ i , j - 1 ] . Encontrar o sufixo z ' requer apenas O ( 1 ) tempoamortizadopor célula, mas calcular A s [ i , j ] com uma abordagem de força bruta leva O ( | zAs[i,j]A[i,j−|z′|−1]A[i,j−1]z′O(1)As[i,j] hora. Provavelmente existe uma maneira de fazer isso de forma mais eficiente, mas não consigo encontrá-lo agora.O(|z′|)
Na pior das hipóteses, o algoritmo leva , mas uma análise melhor deve ser possível. A distância de edição resultante com exclusões longas e cópia de substring não é simétrica, mas isso não deve ser um problema. Afinal, geralmente é mais fácil alcançar a string vazia de uma não vazia do que o contrário.O(min(|x|⋅|y|2,|x|2⋅|y|))