8

我有两个要对齐的 100 个字符的数组(最大,可以小于或不同的大小)。当字符与另一个字符不同时,我想添加一个“-”。我发现了基于动态规划的Needleman-Wunsch算法和基于动态规划的通用局部对齐方法Smith-Waterman算法,但它们对于我想做的事情来说似乎太复杂了。我只需要一个简单的Java算法,大概不到50行,这段代码会被翻译成汇编语言,所以我需要一个简单的算法。

有没有办法用 diff 算法进行这种对齐?如果是的话,有人可以指出我该怎么做吗?我在 biostar 部分进行了搜索,但似乎我需要使用我提到的两种算法。

英语不是我的母语,所以也许我搜索了错误的关键字。

我的程序已经使用 Needleman 算法及其大约 200 行(ish)代码。

所需输入/输出示例:

Input
Array 1 : MKNLASREVNIYVNGKLV
Array 2 : QMASREVNIYVNGKL


Output
Array 1 (or a simple print) : -MKNLASREVNIYVNGKLV 
Array 2 (or a simple print) : QM---ASREVNIYVNGKL-
4

2 回答 2

11

使用完全符合您要求的 Levenshtein 距离的变体:

输出

-MKNLASREVNIYVNGKLV
QM---ASREVNIYVNGKL-

代码:

public class Main {
    public static void main(String[] args) {
        String[] aligned = align("MKNLASREVNIYVNGKLV", "QMASREVNIYVNGKL");
        System.out.println(aligned[0]);
        System.out.println(aligned[1]);
    }

    public static String[] align(String a, String b) {
        int[][] T = new int[a.length() + 1][b.length() + 1];

        for (int i = 0; i <= a.length(); i++)
            T[i][0] = i;

        for (int i = 0; i <= b.length(); i++)
            T[0][i] = i;

        for (int i = 1; i <= a.length(); i++) {
            for (int j = 1; j <= b.length(); j++) {
                if (a.charAt(i - 1) == b.charAt(j - 1))
                    T[i][j] = T[i - 1][j - 1];
                else
                    T[i][j] = Math.min(T[i - 1][j], T[i][j - 1]) + 1;
            }
        }

        StringBuilder aa = new StringBuilder(), bb = new StringBuilder();

        for (int i = a.length(), j = b.length(); i > 0 || j > 0; ) {
            if (i > 0 && T[i][j] == T[i - 1][j] + 1) {
                aa.append(a.charAt(--i));
                bb.append("-");
            } else if (j > 0 && T[i][j] == T[i][j - 1] + 1) {
                bb.append(b.charAt(--j));
                aa.append("-");
            } else if (i > 0 && j > 0 && T[i][j] == T[i - 1][j - 1]) {
                aa.append(a.charAt(--i));
                bb.append(b.charAt(--j));
            }
        }

        return new String[]{aa.reverse().toString(), bb.reverse().toString()};
    }
}
于 2013-02-23T17:36:36.447 回答
1

你对问题的描述立刻让我想到了Levenshtein 距离及其相关算法,它很简单(绝对少于 50 行)但也是基于动态编程的。

原始算法只是计算所需的更改次数,但可以轻松修改它以找到所需的插入、删除和替换。实际上,我不确定您是否甚至想处理替换,例如 ABC 和 ADC 将如何对齐?

于 2013-02-23T17:14:17.877 回答