您可以使用具有仿射间隙成本的成对对齐来执行此操作,这两个长度分别为 n 和 m 的字符串需要 O(nm) 时间。
首先是一件事:就使用的位或字节而言,无法找到可证明的最小补丁。那是因为如果有这样的方法,那么shortest_patch(x, y)
计算它的函数可以s
通过调用它来找到任何给定字符串的可证明最小压缩shortest_patch('', s)
,并且 Kolmogorov 复杂性告诉我们给定字符串的最短可能压缩在形式上是不可计算的. 但是,如果编辑倾向于在空间中聚集,就像它们似乎在这里一样,那么肯定有可能找到比使用通常的 Levenshtein 距离算法生成的更小的补丁。
编辑脚本
补丁在 CS 中通常称为“编辑脚本”。x
找到用于将一个字符串转换为另一个字符串的最小(就插入次数加上删除次数而言)编辑脚本y
等效于找到最佳成对对齐方式,其中每对相等的字符都有值 0,每对不相等的字符都有值-inf,并且一个字符串中的字符与-
间隙字符对齐的每个位置的值都为 -1。对齐很容易可视化:
st--ing st-i-ng
stro-ng str-ong
这些是字符串sting
和的 2 个最佳对齐方式strong
,每个在模型下的成本为 -3。如果不等字符对的值是 -1 而不是 -inf,那么我们得到的对齐成本等于 Levenshtein 距离(插入的数量,加上删除的数量,加上替换的数量):
st-ing sti-ng
strong strong
这些是新模型下的 2 个最佳对齐方式,每个的成本为 -2。
要查看它们如何与编辑脚本对应,我们可以将顶部字符串视为“原始”字符串,将底部字符串视为“目标”字符串。包含不相等字符对的列对应于替换,-
顶行包含 a 的列对应于字符的插入,-
底行包含 a 的列对应于字符的删除。您可以使用“指令”(C)opy、(D)elete、(I)nsert 和 (S)ubstitute 从对齐创建编辑脚本。每条指令后跟一个数字,表示从对齐中消耗的列数,在 I 和 S 的情况下,相应的插入或替换字符数。例如,前 2 个对齐的编辑脚本是
C2, I1"r", S1"o", C2 and C2, S1"r", I1"o", C2
增加聚束
现在如果我们有像mississippi
and这样的字符串tip
,我们会发现这两个对齐
mississippi
------tip--
mississippi
t---i----p-
两者都具有相同的 -9 分:它们都需要相同的插入、删除和替换总数。但是我们更喜欢上面那个,因为它的编辑脚本可以更简洁地描述:D6, S1"t", C2, D2
. 第二个的编辑脚本是S1"t", D3, C1, D4, C1, D1
.
为了让对齐算法也“更喜欢”第一个对齐,我们可以调整间隙成本,以便开始一个间隙块的成本高于继续一个现有的间隙块。如果我们使包含间隙的列在前一列不包含间隙时花费 -2 而不是 -1,那么我们实际上正在做的是惩罚连续的间隙块的数量(因为每个连续的间隙块显然必须有第一个位置)。在这个模型下,上面的第一个对齐现在花费 -11,因为它包含两个连续的间隙块。第二个对齐现在花费 -12,因为它包含三个连续的间隙块。IOW,该算法现在更喜欢第一次对齐。
这个模型,其中每个对齐的位置包含一个间隙成本 g 并且任何连续的间隙列块中的第一个位置成本 g + s,被称为仿射间隙成本模型,Gotoh 给出了一个 O(nm) 算法1982 年:http ://www.genome.ist.i.kyoto-u.ac.jp/~aln_user/archive/JMB82.pdf 。增加间隙开放成本 s 将导致对齐的段聚集在一起。您可以使用各种成本参数,直到获得经验上看起来正确且足够小的对齐(对应于补丁)。