50 lines
1.2 KiB
Python
50 lines
1.2 KiB
Python
"""Damerau-Levenshtein edit distance (true DL, not OSA)."""
|
|
from __future__ import annotations
|
|
|
|
|
|
def damerau_levenshtein(a: str, b: str) -> int:
|
|
la, lb = len(a), len(b)
|
|
if la == 0:
|
|
return lb
|
|
if lb == 0:
|
|
return la
|
|
|
|
last = {}
|
|
INF = la + lb
|
|
d = [[0] * (lb + 2) for _ in range(la + 2)]
|
|
d[0][0] = INF
|
|
for i in range(1, la + 2):
|
|
d[i][0] = INF
|
|
d[i][1] = i - 1
|
|
for j in range(1, lb + 2):
|
|
d[0][j] = INF
|
|
d[1][j] = j - 1
|
|
|
|
for i in range(1, la + 1):
|
|
db = 0
|
|
for j in range(1, lb + 1):
|
|
i1 = last.get(b[j - 1], 0)
|
|
j1 = db
|
|
cost = 1
|
|
if a[i - 1] == b[j - 1]:
|
|
cost = 0
|
|
db = j
|
|
d[i + 1][j + 1] = min(
|
|
d[i][j] + cost,
|
|
d[i + 1][j] + 1,
|
|
d[i][j + 1] + 1,
|
|
)
|
|
if i1 > 0 and j1 > 0:
|
|
d[i + 1][j + 1] = min(
|
|
d[i + 1][j + 1],
|
|
d[i1][j1] + (i - i1 - 1) + 1 + (j - j1 - 1),
|
|
)
|
|
last[a[i - 1]] = i
|
|
|
|
return d[la + 1][lb + 1]
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
print(damerau_levenshtein(sys.argv[1], sys.argv[2]))
|