The core algorithm behind Git Diff - Minimum Edit Distance
The Myers diff algorithm was proposed by Eugene W. Myers in 1986 for computing the minimum edit distance between two sequences. It is the core algorithm of Git diff, GNU diff, and other tools. The algorithm finds differences by searching for the shortest path from the top-left to the bottom-right corner on an 'edit graph', where moving right represents deletion, moving down represents insertion, and diagonal moves represent matches.
Algorithm starts with D=0, incrementally increasing D until finding a path from (0,0) to (N,M). This guarantees finding the shortest edit path.
| Metric | Complexity | Description |
|---|---|---|
| Time Complexity | O((N+M)D) | D is edit distance, worst case D=N+M |
| Worst Case Time | O((N+M)²) | Two completely different sequences |
| Space Complexity | O(N+M) | Only need current and previous row states |
In practice, most differences are small, so average performance is excellent.
def myers_diff(a, b): """Myers差异算法 - 返回编辑距离""" n, m = len(a), len(b) max_d = n + m # V数组存储每个k对角线能到达的最远x坐标 v = {1: 0} for d in range(max_d + 1): for k in range(-d, d + 1, 2): # 决定从哪个方向来 if k == -d or (k != d and v.get(k-1, -1) < v.get(k+1, -1)): x = v.get(k + 1, 0) # 从上方下来(插入) else: x = v.get(k - 1, 0) + 1 # 从左边过来(删除) y = x - k # 沿对角线移动(匹配) while x < n and y < m and a[x] == b[y]: x, y = x + 1, y + 1 v[k] = x if x >= n and y >= m: return d # 找到最短编辑距离 return -1 # 使用示例 a = "ABCDEF" b = "ABXDEF" distance = myers_diff(a, b) print(f"编辑距离: {distance}") # 输出: 2
import java.util.*; public class MyersDiff { /** * Myers差异算法 - 返回编辑距离 */ public static int myersDiff(String a, String b) { int n = a.length(); int m = b.length(); int maxD = n + m; // V数组存储每个k对角线能到达的最远x坐标 Map<Integer, Integer> v = new HashMap<>(); v.put(1, 0); for (int d = 0; d <= maxD; d++) { for (int k = -d; k <= d; k += 2) { int x; // 决定从哪个方向来 if (k == -d || (k != d && v.getOrDefault(k-1, -1) < v.getOrDefault(k+1, -1))) { x = v.getOrDefault(k + 1, 0); } else { x = v.getOrDefault(k - 1, 0) + 1; } int y = x - k; // 沿对角线移动(匹配) while (x < n && y < m && a.charAt(x) == b.charAt(y)) { x++; y++; } v.put(k, x); if (x >= n && y >= m) { return d; } } } return -1; } public static void main(String[] args) { String a = "ABCDEF"; String b = "ABXDEF"; int distance = myersDiff(a, b); System.out.println("编辑距离: " + distance); // 输出: 2 } }