全序列匹配(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)); } }