算法与数据结构 / 序列对齐 DP:一张表跑出四种算法 待审核
unified engine · 2×2 象限

序列对齐 DP:一张表跑出四种算法

LCS(最长公共子序列)、编辑距离(Levenshtein)、Needleman–Wunsch(全局序列比对)看着是三道题,底层却是同一个二维 DP。它们都在一张「行为序列 AA、列为序列 BB」的表上填格:每个格子 F[i][j]F[i][j] 只从对角(替换或匹配)、上(删)、左(插)三个来源里,按 max\maxmin\min 取最优。真正区分这几个算法的,只是每个方向记什么代价、以及取 max\max 还是 min\min 这一组参数。本页把它抽象成一个 spec,用同一个引擎在四者之间切换。

1 · 格子的转移来源

AA 排成行、BB 排成列,F[i][j]F[i][j] 表示 AA 的前 ii 个字符与 BB 的前 jj 个字符之间的最优值。要算它,只需看三个已经算好的邻居,各加上一步操作的代价再聚合:

F[i][j]=agg{F[i1][j1]+d(a,b)对角:a 与 b 对位F[i1][j]+up(a)上:删去 A 的字符 aF[i][j1]+left(b)左:插入 B 的字符 bF[i][j] = \mathrm{agg} \begin{cases} F[i-1][j-1] + d(a, b) & \text{对角:}a\text{ 与 }b\text{ 对位} \\ F[i-1][j] + \mathrm{up}(a) & \text{上:删去 }A\text{ 的字符 }a \\ F[i][j-1] + \mathrm{left}(b) & \text{左:插入 }B\text{ 的字符 }b \end{cases}

其中 agg\mathrm{agg}max\maxmin\min,而 ddup\mathrm{up}left\mathrm{left} 是三个方向各自的代价函数。边界(第一行与第一列)对应「一方为空串」,沿单一方向累积即可。填完整张表后,从终点 F[m][n]F[m][n] 沿方向指针回溯,就能还原出完整的对齐与编辑脚本。

图 1-1 · 单个格子的三个转移来源。可切换来源观察该方向对应哪一步编辑操作。

2 · spec 与算法的对应

把四个算法按两个维度摆成一张 2×2 矩阵。纵轴是聚合方向:max\max 配相似度(分越高越像)对 min\min 配代价(代价越低越像)。横轴是代价取法:朴素的 0 与 1 对带权打分。四个格子恰好落到四个算法。

  • LCS(max\max 加朴素):相等才 +1+1,删插不计,求最长公共子序列。
  • Needleman–Wunsch(max\max 加打分):匹配、失配、gap 各给一个可正可负的得分,求总分最高的全局比对。
  • 编辑距离(min\min 加朴素):增、删、改各记 11,求把 AA 改成 BB 的最少操作数。
  • 带权编辑(min\min 加带权):增、删、改各带不同权重,求最小总代价。
图 2-1 · 同一套填表逻辑在四个 spec 下的表与回溯路径。可点矩阵切换算法、改 AABB 或点预设换输入,并逐帧看填表与回溯;Needleman–Wunsch 与带权编辑另有参数滑块与翻转视角按钮(见 §4)。

这个「换 spec 即换算法」的说法可以验证。给 LCS、编辑距离与 Needleman–Wunsch 各写一份不复用引擎的参考实现,在 14 个词两两组合的 196 组输入上比对,引擎的表末值与三份参考实现逐组一致,无一例外。

3 · 四种 spec 的参数对照

四个算法的差别全部浓缩在下表——同一套 solve(A, B, spec) 填表逻辑,只是喂进去的 ddup\mathrm{up}left\mathrm{left}agg\mathrm{agg} 不同。

四行只在代价函数与聚合方向上不同,填表与回溯的代码完全共用。
算法 对角 d(a,b)d(a, b) up(a)\mathrm{up}(a) left(b)\mathrm{left}(b) agg\mathrm{agg}
LCS a=b ? 1:a = b\ ?\ 1 : -\infty 00 00 max\max
Needleman–Wunsch a=b ? match:mismatcha = b\ ?\ \mathrm{match} : \mathrm{mismatch} gap\mathrm{gap} gap\mathrm{gap} max\max
编辑距离 a=b ? 0:1a = b\ ?\ 0 : 1 11 11 min\min
带权编辑 a=b ? 0:Wsuba = b\ ?\ 0 : W_{\mathrm{sub}} WdelW_{\mathrm{del}} WinsW_{\mathrm{ins}} min\min

LCS 的对角取 -\infty 是因为它不允许替换:两个字符不相等时绝不能走对角占一个匹配位,只能从上或左绕过(即删或插)。把失配的对角代价设成 -\infty,在 max\max 聚合下它永远不会被选中,等于禁掉了替换。编辑距离则相反,替换是合法的一步,失配对角记 11

4 · 相似度与代价的同构

有的算法求 max\max、有的求 min\min,根源是相似度等于代价取负。把一个 spec 的全部代价取负、并把 max\max 翻成 min\min(反之亦然),得到的是同一个问题的另一种说法:最优路径完全不变,只是表里每个数字镜像取负。同样在那 196 组输入上实测,翻转前后的表末值严格互为相反数,回溯出的操作序列一字不差。

警示 · 这解释了为什么生物信息学惯用 Needleman–Wunsch 的得分(max\max)语言,而编辑距离用代价(min\min)语言。两者并非不同算法,只是同一个 DP 在符号上的两种约定。

5 · LCS 与编辑距离的化归

当编辑距离只允许增、删而不允许替换时,它与 LCS 之间有一个精确等式:

indel(A,B)=m+n2LCS(A,B)\mathrm{indel}(A, B) = m + n - 2 \cdot \mathrm{LCS}(A, B)

直觉是:两串各长 mmnn,公共子序列里的那 LCS\mathrm{LCS} 个字符两边都保留,其余 mLCSm - \mathrm{LCS} 个要删、nLCSn - \mathrm{LCS} 个要插。这个等式同样在 196 组输入上逐组核过,无一例外。以 kittensitting 为例:LCS=4\mathrm{LCS} = 4,仅增删的编辑距离是 6+72×4=56 + 7 - 2 \times 4 = 5,而允许替换的编辑距离只有 33——替换省下的正是那两步「删一个再插一个」。

6 · DTW 与时间轴对齐

前面四个算法比的是字符序列。把序列换成数值(音频帧、笔迹坐标、传感器采样),问题就从「怎么改」变成「两条随时间变化、但快慢不同的信号怎么对齐、有多像」,这就是 DTW(dynamic time warping,动态时间规整)。它和编辑距离是近亲:同样一张二维表、同样三方向、同样取 min\min。但有三处关键不同,不能当成第五个 spec 并进上面的引擎。

格子代价是距离:每格付 dist(a,b)=ab\mathrm{dist}(a, b) = |a - b|,是实数,不是 0 与 1 或操作权重。

三方向付同一份代价:D[i][j]=dist(a,b)+min(,,)D[i][j] = \mathrm{dist}(a, b) + \min(\nwarrow, \uparrow, \leftarrow),三个前驱都加同一个 dist\mathrm{dist} 再取最优;编辑距离则是三方向各付各的。

边界是无穷、产物是 warping 路径:D[i][0]=D[0][j]=D[i][0] = D[0][j] = \infty 逼对齐从 (1,1)(1,1) 起;回溯得到的是「一个点对多个点」的时间轴伸缩关系,不是增删改的编辑脚本。

图 6-1 · 两条数值序列的 DTW 对齐,柱高为信号幅度、连线为对齐关系。可选「同峰 · 不同速」预设,看两条形状相同快慢不同的信号如何把峰值拉伸对齐到一起。

建议 · 这是字幕对齐(forced alignment)的内核:已知一段音频与对应文本,把音频特征帧序列与文本音素序列用 DTW 或 HMM 对齐,就能算出「第几个字落在哪个时间区间」,生成逐字高亮的字幕。手势识别同理,把用户画的轨迹与模板轨迹对齐,快慢与点数不同也不影响判定。这类功能在前端通常藏在媒体或手势库内部。

7 · 参考文献

  1. Levenshtein, V. I. (1966). Binary codes capable of correcting deletions, insertions, and reversals. Soviet Physics Doklady, 10(8), 707–710.
  2. Needleman, S. B., & Wunsch, C. D. (1970). A general method applicable to the search for similarities in the amino acid sequence of two proteins. Journal of Molecular Biology, 48(3), 443–453.
  3. Sakoe, H., & Chiba, S. (1978). Dynamic programming algorithm optimization for spoken word recognition. IEEE Transactions on Acoustics, Speech, and Signal Processing, 26(1), 43–49.

相关链接

  • Longest common subsequence Wikipedia 对应 LCS 模式:子序列与子串的区别、DP 递推、回溯还原一条 LCS,以及与编辑距离的化归关系。
  • Levenshtein distance Wikipedia 对应编辑距离模式:增 / 删 / 改各记 1 的经典定义,以及带权(Wagner–Fischer)推广。
  • Needleman–Wunsch algorithm Wikipedia 对应 Needleman–Wunsch 模式:生物信息学里的全局序列比对,match / mismatch / gap 打分矩阵与 max 聚合。
  • Wagner–Fischer algorithm Wikipedia 对应带权编辑模式:把编辑距离推广到「每种操作各带权重」的标准填表算法。
  • 列表 diff / 最小差异更新 本站 · list-diff LCS 的工程应用:用它求两个列表的最长公共子序列,推导出最少的 DOM 增删移动(框架 diff 的核心)。
  • Dynamic time warping Wikipedia 对应本页近亲 DTW 节:数值序列的时间轴对齐,三方向 min DP + dist 代价,以及在语音 / 手势识别里的应用。
  • Forced alignment Wikipedia DTW / HMM 的落地:把音频与已知文本对齐到时间轴,生成逐字字幕的技术。
  • 字符串匹配 本站 · string-search 编辑距离作为「近似匹配 / 模糊搜索」基础的一节,与本页的统一视角互补。