Kısa bir süre önce Wikipedia'da sözde koddan Damerau-Levenshtein mesafe algoritmasını uyguladım. Bunun tam olarak nasıl çalıştığını herhangi bir açıklama bulamadık ve yalancı kod gibi tamamen uninformative değişken adlarını kullanır DA
, DB
, i1
ve j1
sol bu beni başım çizilmeye.
İşte Python'daki uygulamam: https://gist.github.com/badocelot/5327337
Python uygulaması, program boyunca ilerlememe ve neler olduğunu anlamama yardımcı oldu, değişkenleri daha yararlı isimlerle yeniden adlandırdı. Bir referans çerçevem olan Levenshtein mesafesini hesaplamak için Wagner-Fischer yaklaşımına yeterince aşinaydım.
Aşırı uzun olma riski altında, Damerau-Levenshtein'i şu şekilde anlıyorum:
Gizem değişkenleri:
DA
(last_row
kodumda), her öğenin görüldüğü son satırı tutan bir tür haritadır; kodumda gerçek bir Python sözlüğü varDB
(last_match_col
) , geçerli satırınb
içindeki harfle eşleşen son sütunu tutara
i1
(last_matching_row
),DA
içindeki geçerli harfin satır numarasıdırb
j1
potansiyel olarak güncellenmeden öncekiDB
/ değerinin sadece bir kopyasıdırlast_match_col
; kodumdalast_match_col
, bu değiştiği yere taşındım ve bu değişkeni elimine ettim
Transpozisyon maliyeti:
H[i1][j1] + (i-i1-1) + 1 + (j-j1-1)
geçerli karakteri, b
içinde olduğu b
bilinen son karakterle a
(son eşleşme) değiştirmenin maliyetini hesaplar ve aradaki tüm karakterleri toplama veya silme olarak ele alır.
Maliyet bileşenleri:
H[i1][j1]
bir transpozisyon bulmak önceki çalışmayı geçersiz kıldığından, temel maliyeti aktarımdan önceki hesaplamalardaki noktaya geri döndürür(i-i1-1)
geçerli satır ile geçerli karakterle eşleşen son satır arasındaki mesafe, yani gerekli olan silme sayısı(j-j1-1)
geçerli sütun ile eşleşmeli son sütun arasındaki mesafedir; bu, ekleme sayısıdır- Ekstra
+ 1
, sadece aktarımın kendisinin maliyeti
Bu analiz yanlışsa, nerede yanlış yaptığımı bilmek isterim. Dediğim gibi, ben bulamadım herhangi algoritma çevrimiçi nasıl çalıştığı ayrıntılı bir açıklama.
Gelişmiş versiyon?
Bununla birlikte, anlaşılan, aktarılan harfler arasındaki hem ekleme hem de silme maliyetini hesaplayarak kusurlu görünüyordu: bir ekleme ve bir silme, bunun kontrol etmediği bir ikame ile eşdeğerdir.
Her şey doğru ise, çözüm önemsiz olmalıdır: aktarılan harfler arasındaki harflerin maliyeti , ekleme ve silme işlemlerinden daha yüksek olmalıdır : mümkün olduğunca çok sayıda ikame haline getirin ve kalan tüm ekleme veya silme işlemlerini ekleyin.
Yani maliyet:
H[i1][j1] + max((i-i1-1), (j-j1-1)) + 1
İşte bu sürüm için kodum: https://gist.github.com/badocelot/5327427
Bazı basit testlerden, bu doğru görünüyor. Örneğin, "abcdef" -> "abcfad" 2 bir düzenleme mesafesi verir ("d" ve "f" yi transpoze edin, "e" yi "a" olarak değiştirin), orijinal algoritma ise 3 (son üçü) harfler ikame veya 1 aktarma + 1 ekleme + 1 silme).
Şimdi, bunu ilk düşünen ben olamam . Öyleyse, neden onunla karşılaşmadım? Yeterince uzun aramadım mı? Yoksa bunun çalışmasını engelleyen ince bir kusur var mı?