DNA序列编辑距离(实践记录)

137 阅读2分钟

首先理解问题:小R正在研究DNA序列,他需要一个函数来计算将一个受损DNA序列(dna1)转换成一个未受损序列(dna2)所需的最少编辑步骤。编辑步骤包括:增加一个碱基、删除一个碱基或替换一个碱基。 理解:- 你需要计算将一个受损DNA序列(dna1)转换成一个未受损序列(dna2)所需的最少编辑步骤。编辑步骤包括增加一个碱基、删除一个碱基或替换一个碱基。

  • 第一步:初始化:

dp[i][0] = i:将 dna1 的前 i 个字符转换为空字符串需要删除 i 个字符。

dp[0][j] = j:将空字符串转换为 dna2 的前 j 个字符需要添加 j 个字符。

  • 第二步:状态转移:

如果 dna1[i-1] == dna2[j-1],则 dp[i][j] = dp[i-1][j-1]

否则,dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1,分别对应替换、删除和插入操作。

  • 第三步:最终结果:

dp[m][n] 即为将 dna1 转换为 dna2 所需的最少编辑步骤。

代码实现

    public static int solution(String dna1, String dna2) {
        int m = dna1.length();
        int n = dna2.length();
        
        int[][] dp = new int[m + 1][n + 1];
        
        for (int i = 0; i <= m; i++) {
            dp[i][0] = i;
        }
        for (int j = 0; j <= n; j++) {
            dp[0][j] = j;
        }
        
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (dna1.charAt(i - 1) == dna2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i][j - 1])) + 1;
                }
            }
        }
        
        return dp[m][n];
    }

    public static void main(String[] args) {
        System.out.println(solution("AGCTTAGC", "AGCTAGCT") == 2);
        System.out.println(solution("AGCCGAGC", "GCTAGCT") == 4);
    }
}

-总结:这个问题通过动态规划解决,使用二维数组 dp 记录从 dna1 转换到 dna2 的最少编辑步骤。初始化 dp[i][0] 和 dp[0][j] 为 i 和 j,表示删除和插入操作。状态转移时,若字符相同则 dp[i][j] = dp[i-1][j-1],否则取替换、删除、插入中的最小值加一。最终结果为 dp[m][n]