全序列匹配(java)

代码

算法思想:Needleman-Wunsch算法

import java.util.Scanner;
class Data{
    int left, diagonal, up;
    Data(){}
    Data(int a, int b, int c){
        left = a;
        diagonal = b;
        up = c;
    }
    public String toString(){
        return String.format("(%2d, %2d, %2d)",left, diagonal, up);
    }
}
public class Blast {
    // 反转字符串
    public static String reverse(String s) {
        String str = "";
        char[] a = s.toCharArray();
        for (int i = a.length - 1; i >= 0; i--) {
            str += a[i];
        }
        return str;
    }

    public static String pairaln(String s1, String s2) {
        // 得分情况
        int MATCH = 2; // 匹配
        int MISMATCH = -1; // 匹配失败
        int GAP = -1; // 存在gap

        // 初始化
        int length1 = s1.length() + 1;
        int length2 = s2.length() + 1;
        int[][] score = new int[length2][length1];
        int[][] pointer = new int[length2][length1];
        Data[][] data = new Data[length2][length1];
        score[0][0] = 0;
        pointer[0][0] = 0; // 记录选择了那个数据,按照left,diagonal,up顺序
        data[0][0] = new Data(0, 0, 0);

        for (int j = 1; j < length1; j++) {
            score[0][j] = GAP * j;
            pointer[0][j] = 1;
            data[0][j] = new Data(GAP * j, GAP * j, GAP * j);
        }
        for (int i = 1; i < length2; i++) {
            score[i][0] = GAP * i;
            pointer[i][0] = 3;
            data[i][0] = new Data(GAP * i, GAP * i, GAP * i);
        }
        // dp
        for (int i = 1; i < length2; i++) {
            int letter2 = s2.charAt(i - 1);
            for (int j = 1; j < length1; j++) {
                int diagonal_score, left_score, up_score;
                int letter1 = s1.charAt(j - 1);
                diagonal_score = letter1 == letter2 ?
                        score[i - 1][j - 1] + MATCH : score[i - 1][j - 1] + MISMATCH;
                up_score = score[i - 1][j] + GAP;
                left_score = score[i][j - 1] + GAP;
                data[i][j] = new Data(left_score, diagonal_score, up_score);
                if (diagonal_score >= Math.max(up_score, left_score)) {
                        score[i][j] = diagonal_score;
                        pointer[i][j] = 2;
                } else {
                    if (up_score >= left_score) {
                        score[i][j] = up_score;
                        pointer[i][j] = 3;
                    } else {
                        score[i][j] = left_score;
                        pointer[i][j] = 1;
                    }
                }
            }
        }
        // 得分矩阵
        for (int k = 0; k < length2; k++) {
            for (int l = 0; l < length1; l++) {
                System.out.print(data[k][l] + " ");
            }
            System.out.println();
        }

        // 回溯
        int j = length1 - 1;
        int i = length2 - 1;
        String align1 = "";
        String align2 = "";

        while (true) {
            if (pointer[i][j] == 0) break;
            if (pointer[i][j] == 2) {
                align1 += s1.charAt(j - 1);
                align2 += s2.charAt(i - 1);
                i--;
                j--;
            }
            if (pointer[i][j] == 1) {
                align1 += s1.charAt(j - 1);
                align2 += "-";
                j--;
            }
            if (pointer[i][j] == 3) {
                align1 += "-";
                align2 += s2.charAt(i - 1);
                i--;
            }
        }
        // 翻转
        align1 = reverse(align1);
        align2 = reverse(align2);

        return "序列:\n" + s1 + "\n" + s2 + "\n" + "比对结果:\n" + align1 + "\n" + align2 + "\n";
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("请输入第一条序列:");
        String seq1 = in.next();
        System.out.println("请输入第二条序列:");
        String seq2 = in.next();
        System.out.println(pairaln(seq1, seq2));
    }
}

 

posted @ 2020-07-12 14:55  德狗咬不过狗  阅读(286)  评论(0编辑  收藏  举报