Levenshtein Distance - 動的プログラミングによる効率的な実装
編集距離(レーベンシュタイン距離)は、2つの文字列間での最小編集操作数を計算するアルゴリズムです。挿入・削除・置換の3つの操作を使用して、一つの文字列を別の文字列に変換するのに必要な最小回数を求めます。
def minDistance(self, word1: str, word2: str) -> int:
"""
編集距離 (Levenshtein Distance)
Args:
word1 (str): 最初の文字列
word2 (str): 比較対象の文字列
Returns:
int: 最小編集距離
"""
# 型検証
if not isinstance(word1, str) or not isinstance(word2, str):
raise TypeError("Both inputs must be strings")
m, n = len(word1), len(word2)
# 片方が空文字の場合
if m == 0:
return n
if n == 0:
return m
# 空間最適化: 常に短い方を n にする
if n > m:
word1, word2 = word2, word1
m, n = n, m
# dp[j] = word1[0:i] と word2[0:j] の編集距離
prev = list(range(n + 1))
for i in range(1, m + 1):
curr = [i] + [0] * n
for j in range(1, n + 1):
if word1[i - 1] == word2[j - 1]:
curr[j] = prev[j - 1]
else:
curr[j] = 1 + min(
prev[j], # 削除
curr[j - 1], # 挿入
prev[j - 1] # 置換
)
prev = curr
return prev[n]
上記のテーブルは動的プログラミングの各ステップを示します。各セルは、対応する部分文字列間の最小編集距離を表します。
この実装では、従来の2次元配列を使用したアプローチと比較して、空間計算量を大幅に削減しています。常に短い文字列をベースとして計算することで、メモリ使用量を最小化しています。
def minDistance_fast(self, word1: str, word2: str) -> int:
"""
競技プログラミング向け最適化版
- 入力検証を省略
- 空間 O(min(m, n))
"""
if len(word2) > len(word1):
word1, word2 = word2, word1
m, n = len(word1), len(word2)
prev = list(range(n + 1))
for i in range(1, m + 1):
curr = [i] + [0] * n
for j in range(1, n + 1):
if word1[i - 1] == word2[j - 1]:
curr[j] = prev[j - 1]
else:
curr[j] = 1 + min(prev[j], curr[j - 1], prev[j - 1])
prev = curr
return prev[n]
高速版では型チェックを省略し、より簡潔な実装となっています。競技プログラミングなど、パフォーマンスが重視される場面で使用されます。