概述
本文参考:https://blog.jcoglan.com/2017/02/12/the-myers-diff-algorithm-part-1/
每个开发者多少都接触过git的diff功能,如下图:
该功能能够展示出某个文件的改动信息,非常便于开发者的日常开发。
本文将探讨下此功能实现的原理。
myers diff 做了啥
引用个例子
a = ABCABBA
b = CBABAC
现在要找出ab之间的diff。仔细想一想,我们会发现其实两者之间的diff情况是有无数个的,比如可以找到以下几种情况:
1. - A 2. - A 3. + C
- B + C - A
C B B
- A - C - C
B A A
+ A B B
B - B - B
A A A
+ C + C + C
但是实际我们使用的时候,期望的看到的是最优的一种情况,最好是满足以下两个标准的:
- diff的内容最少
- 删除的内容在增加的内容之前
根据这两个标准,这个例子中我们可以得到最优解,如下:
- A
- B
C
+ B
A
B
- B
A
+ C
myers diff 思路
myers diff算法中,将 寻找 diff 的过程表示为了图搜索,如下图:
A B C A B B A
o-----o-----o-----o-----o-----o-----o-----o 0
| | | \ | | | | |
C | | | \ | | | | |
| | | \ | | | | |
o-----o-----o-----o-----o-----o-----o-----o 1
| | \ | | | \ | \ | |
B | | \ | | | \ | \ | |
| | \ | | | \ | \ | |
o-----o-----o-----o-----o-----o-----o-----o 2
| \ | | | \ | | | \ |
A | \ | | | \ | | | \ |
| \ | | | \ | | | \ |
o-----o-----o-----o-----o-----o-----o-----o 3
| | \ | | | \ | \ | |
B | | \ | | | \ | \ | |
| | \ | | | \ | \ | |
o-----o-----o-----o-----o-----o-----o-----o 4
| \ | | | \ | | | \ |
A | \ | | | \ | | | \ |
| \ | | | \ | | | \ |
o-----o-----o-----o-----o-----o-----o-----o 5
| | | \ | | | | |
C | | | \ | | | | |
| | | \ | | | | |
o-----o-----o-----o-----o-----o-----o-----o 6
0 1 2 3 4 5 6 7
找到图中从左上到右下的最短路径就是找到了最优的diff。
右表示“删除”,向下表示”新增“,对角线则表示“原内容保持不动“。
寻找路径需要满足两个特点:
- 路径长度最短(对角线不算长度)
- 先向右,再向下(先删除,后新增)
动态规划
如此,要找到第n步的最短路径,那么就需要找到第n-1步的最短路径,以此类推,就需要从第2步,第1步开始就走最优解。
就拿(2,2)这个点举例,可以到达它的路径有以下:
(0,0)->(1,0)->(2,2)
(0,0)->(1,0)->(1,1)->(1,2)->(2,2)
(0,0)->(1,0)->(1,1)->(2,1)->(2,2)
(0,0)->(1,0)->(2,0)->(2,1)->(2,2)
(0,0)->(0,1)->(2,2)
(0,0)->(0,1)->(1,1)->(1,2)->(2,2)
(0,0)->(0,1)->(1,1)->(2,1)->(2,2)
(0,0)->(0,1)->(0,2)->(1,2)->(2,2)
由于要遵循先右后下的原则,因此到达(2,2)最优的方案就是
(0,0)->(1,0)->(2,2)
倘若从(0,0)开始走,每条路径仅保留最优解的话,最终可以得到有以下路径:
0,0 --- 1,0 --- 3,1 --- 5,2 --- 7,3
| | |
| | |
0,1 2,2 5,4 --- 7,5
| | |
| | |
2,4 --- 4,5 5,5 7,6
| | |
| | |
3,6 4,6 5,6
myers diff 概念
myers diff 中引入了k和d 两个概念来方便计算最短路径。
k: k=x-y,x与y分别是横竖方向上的位置
d: 走的步数 ,走斜线不算步数
根据这两个参数可以得到下图:
在d相同的情况下,k越小,越接近终点。
因此最优解也就可以筛选出来了。