動的計画法で 2 つの単語の編集距離を求める

1 文字の​挿入、​削除、​置き換えを​何回すれば、​ある​単語を​別の​単語に​変えられるかの​最小を​求めます。​2 次元の​表で​考え、​記憶を​表の​ 1 行分まで​縮める​ところまで​詰める​練習です。

海外で定番の問題リスト 4 本のうち 2 本に入っています (NeetCode 150、LeetCode Top Interview 150)

問題

検索窓の打ち間違いを直す「もしかして」の機能を作っています。打たれた単語 src を、辞書の単語 dst に変えたいとき、次の 3 つの操作を合わせて最も少なくて何回で済むかを返す関数を書いてください。

  • どこかに 1 文字を挿入する
  • どこかの 1 文字を削除する
  • どこかの 1 文字を別の文字に置き換える

条件は次の通りです。

  • 操作はどれも 1 回と数えます。3 つの操作を好きな順に、何回でも混ぜて使えます
  • src と dst の長さは、どちらも 0 以上 500 以下です。空の文字列も来ます
  • 文字は英小文字だけです

入力と出力の例

例 1

先頭の s を削除し、p を m に置き換えれば 2 回です。

入力

src = "spoon"
dst = "moon"

出力

2

例 2

前から 1 文字ずつ置き換えると 5 回かかります。先頭の s を削除し、末尾に s を挿入すれば 2 回で済みます。

入力

src = "stone"
dst = "tones"

出力

2

例 3

空の文字列からは、全部の文字を挿入するしかありません。

入力

src = ""
dst = "web"

出力

3

面接での聞かれ方

面接では、短い一文で渡されたあと、計算量を詰める問いが続きます。

  • 「2 つの文字列を、挿入、削除、置き換えで同じにする最小の手数を返してください」
  • 書き終えると「表の記憶を減らせますか?」と聞かれます。2 次元の表から 1 行分へ縮められるかが、シニアとして見られるところです
  • 「どの操作をしたかも返せますか?」「置き換えだけ 2 回と数えたら?」と、表の中身を変える問いが続くこともあります

文字ごとに左から合わせていく欲張りは、例 2 のように外れます。表の 1 つの欄が何を表すかを、書く前に言葉で決めておきます。

アルゴリズムのチートシートの「動的計画法 (DP)」に、​この​型の​要点を​表と​コードで​まとめています。

main.py
def edit_distance(src, dst):
    # ここに書きます
    pass


# 「実行」を押すと、この行の結果が出ます
print(edit_distance("spoon", "moon"))

できているか「例で確かめる」を押すと、問題の例を全部この関数に渡して、通ったかをここに出します