基 因学的一个主要主题就是比较 DNA 序列并尝试找出两个序列的公共部分。如果两个 DNA 序列有类似的公共子序列,那么这些两个序列很可能是同源的 。在比对两个序列时,不仅要考虑完全匹配的字符,还要考虑一个序列中的空格或间隙(或者,相反地,要考虑另一个序列中的插入部分)和不匹配,这两个方面都 可能意味着突变。在序列比对中,需要找到最优的比对(最优比对大致是指要将匹配的数量最大化,将空格和不匹配的数量最小化)。如果要更正式些,您可以确定 一个分数,为匹配的字符添加分数、为空格和不匹配的字符减去分数。
全局序列比对 尝试找到两个完整的序列 S1 和 S2 之间的最佳比对。以下面两个 DNA 序列为例:
- S1 = GCCCTAGCG
- S2 = GCGCAATG
如果为每个匹配字符一分,一个空格扣两分,一个不匹配字符扣一分,那么下面的比对就是全局最优比对:
- S1' = GCCCTAGCG
- S2' = GCGC -AATG
连字符(-)代表空格。在 S2' 中有五个匹配字符,一个空格(或者反过来说,在 S1' 中有一个插入项),有三个不匹配字符。这样得到的分数是 (5 * 1) + (1 * -2) + (3 * -1) = 0,这是能够实现的最佳结果。
使用局部序列比对 ,不必对两个完整的序列进行比对;可以在每个序列中使用某些部分来获得最大得分。使用同样的序列 S1 和 S2 ,以及同样的得分方案,可以得到以下局部最优比对 S1'' 和 S2'' :
- S1 = GCCCTAGCG
- S1'' = GCG
- S2'' = GCG
- S2 = GCGCAATG
虽然这个局部比对恰好没有不匹配字符或空格,但是一般情况下,局部比对可能存在不匹配字符或空 格。这个局部比对的得分是 (3 * 1) + (0 * -2) + (0 * -1) = 3。(最佳局部比对的得分要大于或等于最佳全局比对的得分,这是因为全局比对 也属于 局部比对。)
Needleman-Wunsch 算法 用来计算全局比对。它的思路与 LCS 算法相似。这个算法也使用二维表格,一个序列沿顶部展开,一个序列沿左侧展开。而且也能通过以下三个途径到达每个单元格:
- 来自上面的单元格,代表将左侧的字符与空格比对。
- 来自左侧的单元格,代表将上面的字符与空格比对。
- 来自左上侧的单元格,代表与左侧和上面的字符比对(可能匹配也可能不匹配)
我首先给出完整的表格(参见图 7),在解释如何填充表格的时候可以返回来查看它:
图 7.带有回溯的填充好的 Needleman-Wunsch 表格
首先,必须初始化表格。这意味着填充第二行和第二列的分数和指针。填充第二行的操作意味着使用 位于顶部的第一个序列中的字符,并使用空格,而不是使用左侧从上到下的序列中的第一个字符。空格的扣分是 -2,所以每次使用空格的时候,就给以前的单元格加了 -2 分。以前的单元格是左侧的单元格。这就说明了在第二行中为什么得到了 0, -2, -4, -6, ... 这样的序列。用相似的方式得到第二列的得分和指针。
接下来,需要填充余下的单元格。同 LCS 算法一样,对于每个单元格,都有三个选择,要从中选择最大的。可以从上面、左侧、左上侧到达每个单元格。假设 S1 和 S2 是要比对的字符串,S1' 和 S2' 是生成的比对中的字符串。从上面到达单元格相当于将左面的字符从 S2 加入 S2' ,跳过上面的 S1 中的当前字符,并在 S1' 中加入一个空格。因为一个空格的分数是 -2,所以当前单元格的得分要从上面的单元格得分减 2 得到。类似的,将左边的单元格得分减 2,可以从左侧到达空单元格。最后,可以将上面的字符加入到 S1' 中,将左边的字符加入到 S2' 中。这就相当于从左上侧进入空白单元格。这两个字符将会匹配,在这种情况下,新的得分就是左上侧单元格的得分减 1。在这三种可能性当中,选择得分最大的一个(如果得分相等,可以从得分高的单元格中从任选一个)。观察 图 7 中的指针,能够找到这三种可能性的示例。
接下来,需要得到实际的比对字符串 — S1' 和 S2' — 以及比对的得分。右下角单元格中的得分包含 S1 和 S2 的最大比对得分,就像在 LCS 算法中包含 LCS 的长度一样。而且,与 LCS 算法类似,要获得 S1' 和 S2' ,要从右下角单元格开始沿着指针回溯,反向构建 S1' 和 S2' 。从表格的构建过程可知,从上向下对应着将左侧字符从 S2 加入到 S2' 中,将空格加入 S1' 中;从左向右对应着将上面的字符从 S1 加入到 S1' 中,将空格加入 S2' 中;而向下和向右移动意味着分别将来自 S1 和 S2 的字符加入 S1' 和 S2' 。
Needleman-Wunsch 中使用的回溯代码与 Smith-Waterman 中局部比对的回溯代码基本相同,区别只是开始的单元格以及如何知道何时结束回溯。
通过回溯能够得到本节开始时提到的最优全局比对:
- S1' = GCCCTAGCG
- S2' = GCGC -AATG