1. kitten -> sitting は 3
  2. horse -> ros は 3
  3. 同一文字列は 0
  4. 空文字 vs abc は 3
  5. abc vs 空文字 は 3
  6. intention -> execution は 5
コース一覧
コンピューターサイエンス上級:アルゴリズムとデータ構造
編集距離 (レーベンシュタイン距離)

コンピューターサイエンス上級:アルゴリズムとデータ構造

探索、ソート、木、グラフ、動的計画法、貪欲法など、競技プログラミングや技術面接で問われる高度なアルゴリズムとデータ構造を学べるコースです。基本的な CS の知識を持ち、アルゴリズム力を伸ばしたい学習者や、外資・大手の技術面接対策をしたい方を対象としています。約 13 時間 (1 日 30 分 × 26 日) で 50 レッスンを修了でき、修了後はコーディング面接の実装問題を構造的に解けるようになります。

1
連結リスト
01. リンクリスト構築と長さの計算5分
02. リンクリストの反転5分
03. リンクリストのサイクル検出5分
04. ソート済みリンクリストの merge5分
05. リンクリストの中央ノード取得5分
06. ソート済みリストの重複削除5分
07. 第1章まとめクイズ5分
2
二分木
01. 二分木の in-order 走査5分
02. 二分木の pre-order 走査5分
03. 二分木の post-order 走査5分
04. 二分木の幅優先走査 (BFS)5分
05. 二分木の高さ5分
06. 二分木の平衡判定5分
07. 第2章まとめクイズ — 二分木5分
3
探索木 (BST)
01. BST に値を挿入する5分
02. BST から値を検索する5分
03. BST の最小値と最大値5分
04. BST 妥当性チェック5分
05. BST で k 番目に小さい値5分
06. BST から値を削除する5分
07. 第 3 章 まとめクイズ5分
4
ハッシュとセット
01. hashmap で頻度集計5分
02. キーでグループ化5分
03. two sum (hash で O(n))5分
04. 部分配列の和 = k の個数5分
05. 最長連続部分列5分
06. 集合の積 (intersection)5分
07. 第4章まとめクイズ5分
5
グラフ
01. グラフ BFS で連結成分サイズを求める5分
02. グラフ DFS で連結成分の数を数える5分
03. グラフのパス存在判定5分
04. BFS で最短経路の長さを求める5分
05. トポロジカルソート5分
06. 2 部グラフ判定5分
07. ダイクストラ法 — 重み付きグラフの最短経路15分
08. 第5章まとめクイズ — グラフ5分
6
動的計画法 (上級)
01. 編集距離 (レーベンシュタイン距離)5分
02. 最長増加部分列(LIS)の解法 ── AOJ 2430 対応の動的計画法5分
03. 最大部分配列和 (Kadane)5分
04. 隣り合わない最大値 (House Robber)5分
05. グリッド経路数 (Unique Paths)5分
06. 単語分割可能か (Word Break)5分
07. 第6章まとめクイズ — 動的計画法 (上級)5分
7
総合データ構造と関数型
01. map と filter を組み合わせる5分
02. reduce で積を計算5分
03. 関数合成5分
04. カリー化5分
05. trie の単純検索 (prefix マッチ)5分
06. Union-Find (連結成分数)5分
07. 最終総まとめクイズ5分

編集距離 (レーベンシュタイン距離)

同じ計算を何度もしている

kitten を sitting に変えるには、1 文字ずつ「置き換える」「消す」「足す」のどれかを選びます。最小で何回で済むかを知りたい。これが編集距離で、スペルの候補出し、DNA の比較、git diff の親戚まで、同じ考え方が使われています。

素直に考えると、先頭の 1 文字ごとに 3 通りの選択肢があり、その先でまた 3 通りに分かれます。10 文字なら分岐は数万通りです。

ここで手を止めて、分岐の中身を見てみます。「kitten の後ろ 4 文字を sitting の後ろ 5 文字に変えるには」という同じ問いが、別々の枝の先で何度も出てきます。同じ問いを毎回ゼロから解き直しているのが、爆発の正体です。

もっと分かりやすい例で確かめます。

Python

def fib(n): if n < 2: return n return fib(n - 1) + fib(n - 2)

fib(5) を計算すると fib(2) は 3 回、fib(1) は 5 回呼ばれます。fib(30) では fib(2) が 50 万回を超えます。答えは毎回同じなのにです。

Python

memo = {} def fib(n): if n < 2: return n if n not in memo: memo[n] = fib(n - 1) + fib(n - 2) return memo[n]

1 度出した答えを取っておくのがメモ化、小さいほうから順に埋めていくのがボトムアップ、埋めるときの計算式が漸化式です。用語はこれだけで、あとはどんな表を作るかの話になります。

1 マスは 3 つの手から決まる

表の縦を「s1 を何文字まで見たか」、横を「s2 を何文字まで見たか」にします。マスの中身は「そこまでを一致させるのに必要な最小の回数」です。

今見ている 2 文字が同じなら、何もしなくてよいので、左上のマスの値がそのまま入ります。違うなら、次の 3 つを比べて一番小さいものに 1 を足します。

  • 上のマス — s1 の文字を 1 つ消した場合
  • 左のマス — s2 の文字を 1 つ足した場合
  • 左上のマス — 1 文字を置き換えた場合

どれがどれか迷ったら、上に動くと s1 が 1 文字短くなり、左に動くと s2 が 1 文字短くなる、と手を動かして確かめてください。左上は両方が同時に短くなるので、置き換えです。

一番上の行と一番左の列は、片方が空文字列のときです。空から 3 文字を作るには 3 回足すしかないので、0、1、2、3 と並びます。ここを埋めないまま 0 のままにすると、表全体が小さくなって答えがずれます。

答えは右下のマスです。左上から右下へ向かって、行ごとに順に埋めていけば、必要な値は必ず埋まった後になります。

添字が 1 つずれる

表には空文字列の行と列があるので、m + 1 行 n + 1 列を用意します。そのぶん、マスの番号と文字の番号が 1 つずれます。

i 番目のマスは「最初の i 文字」を表すので、比べる文字は i 番目ではなく i - 1 番目です。ここを合わせ忘れると、最初の 1 文字を無視した答えや、範囲外のエラーになります。

やってみよう

  • horse と ros の表を紙に書いて埋める。答えは 3
  • 同じ文字列同士なら、左上から右下まで斜めに 0 が並ぶ
  • 片方が空文字列なら、答えはもう片方の文字数と同じになる

要件

  1. 戻り値は s1 を s2 に変えるのに必要な最小編集回数 (整数)
  2. 編集操作は挿入・削除・置換の 3 種類で、それぞれ 1 回として数える
  3. 二次元 DP テーブルを用いて O(m * n) で計算すること

入出力例

editDistance("kitten", "sitting") → 3 editDistance("horse", "ros") → 3 editDistance("abc", "abc") → 0 editDistance("", "abc") → 3 editDistance("abc", "") → 3 editDistance("intention", "execution") → 5

ヒント

dp[i][j] = s1 の最初 i 文字を s2 の最初 j 文字に変える最小回数、と定義する

s1[i-1] == s2[j-1] なら dp[i][j] = dp[i-1][j-1]、そうでなければ 1 + min(削除, 挿入, 置換)

境界条件 dp[i][0] = i、dp[0][j] = j を最初に埋めてから二重ループで遷移する

生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/05/19·更新 2026/08/26

関連レッスン

  • 最長増加部分列(LIS)の解法 ── AOJ 2430 対応の動的計画法

    最長増加部分列(LIS)を動的計画法で解く方法を、AOJ/Aizu 2430 のような問題に対応する形で解説。O(n^2)とO(n log n)の2解法をコード付きで紹介します。

  • 最大部分配列和 (Kadane)

    連続する部分配列の最大和を、Kadane のアルゴリズムで線形時間 O(n) で求めます。

  • 隣り合わない最大値 (House Robber)

    隣り合う要素を同時に選べないという制約の下、配列から取り出せる最大合計を DP で求めます。

  • グリッド経路数 (Unique Paths)

    右と下にのみ進めるグリッドの上で、左上から右下に至る経路の総数を二次元 DP で数えます。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • メモ化計算済みの結果を保存して再利用する
  • 戻り値呼び出し元への返答を表す点線矢印
  • テーブルDB の表 (Excel のシートみたいなもの)
main.py
学習モード
エディタを読み込んでいます

メモ

編集距離 (レーベンシュタイン距離)

⌘S で保存