//% Copyright(c) 2006, Shinichi Morishita. All Rights Reserved. public class Chapter6_ApproximateStringMatching { final static double matchScore = 1; final static double mismatchPenalty = -0.5; final static double gapPenalty = -0.5; final static double startupGapPenalty = -2; public static void NeedlemanWunsch(int[] stringX, int[] stringY){ // Initialize constants. int stringXlen = stringX.length; int stringYlen = stringY.length; double[][] score = new double[stringXlen+1][stringYlen+1]; // Initialize the score array. for(int x=0; x < stringXlen+1; x++) score[x][0] = gapPenalty*x; for(int y=0; y < stringYlen+1; y++) score[0][y] = gapPenalty*y; // Inductive steps. double oneScore; for(int x=1; x < stringXlen+1; x++){ for(int y=1; y < stringYlen+1; y++){ if(stringX[x-1] == stringY[y-1]) oneScore = matchScore; else oneScore = mismatchPenalty; score[x][y] = max( score[x-1][y-1] + oneScore, score[x-1][y] + gapPenalty, score[x][y-1] + gapPenalty); } } // Print out the score. System.out.println("Alignment score = "+score[stringX.length][stringY.length]); // Restore the alignment from the bottom-right to the top-left. int[][] alignment = new int[stringXlen+stringYlen+1][2]; int i = 0; int x,y; for(x = stringX.length, y = stringY.length; !(x == 0 && y == 0); i++){ if(0 < x && 0 < y && stringX[x-1] == stringY[y-1]) oneScore = matchScore; else oneScore = mismatchPenalty; if(0 < x && 0 < y && score[x][y] == score[x-1][y-1] + oneScore){ alignment[i][0] = stringX[x-1]; alignment[i][1] = stringY[y-1]; x = x-1; y = y-1; }else if(0 < x && 0 <= y && score[x][y] == score[x-1][y] + gapPenalty){ alignment[i][0] = stringX[x-1]; alignment[i][1] = -1; x = x-1; }else if(0 <= x && 0 < y && score[x][y] == score[x][y-1] + gapPenalty){ alignment[i][0] = -1; alignment[i][1] = stringY[y-1]; y = y-1; } } printAlignment(alignment, i-1); } public static void NeedlemanWunschHirschberg(int[] stringX, int[] stringY){ double[][] tmpScore = new double[3][stringY.length+1]; int[] footprints = new int[stringX.length+1]; double[] footprintScores = new double[stringX.length+1]; footprints[0] = 0; footprintScores[0] = 0; footprints[stringX.length] = stringY.length; NWHrecursion(footprints, footprintScores, tmpScore, stringX, stringY, 0, 0, stringX.length, stringY.length); // Print the score of the optimal alignment. System.out.println("Alignment score = "+footprintScores[stringX.length]); // Print out the alignment by parsing footprints and footprintScores. int[][] alignment = new int[stringX.length+stringY.length+1][2]; int x, j; // x and j scan footprints and alignment. for( j=0, x=1; x < footprints.length; x++){ if( footprints[x-1] == footprints[x]){ // Insert a gap in stringY. alignment[j][0] = stringX[x-1]; alignment[j][1] = -1; j++; }else{ // Insert gaps in stringX. double diffScores = footprintScores[x]-footprintScores[x-1]; int diffFootprints = footprints[x]-footprints[x-1]; if(diffScores == matchScore + gapPenalty*(diffFootprints-1)){ boolean match = false; for(int y=footprints[x-1]+1; y <= footprints[x]; y++, j++){ if(stringX[x-1] == stringY[y-1] && !match){ alignment[j][0] = stringX[x-1]; match=true; }else alignment[j][0] = -1; alignment[j][1] = stringY[y-1]; } }else if(diffScores == gapPenalty*(diffFootprints+1)){ for(int y=footprints[x-1]+1; y <= footprints[x]; y++, j++){ alignment[j][0] = -1; alignment[j][1] = stringY[y-1]; } alignment[j][0] = stringX[x-1]; alignment[j][1] = -1; j++; }else if(diffScores == mismatchPenalty + gapPenalty*(diffFootprints-1)){ for(int y=footprints[x-1]+1; y <= footprints[x]; y++, j++){ if(y == footprints[x]) alignment[j][0] = stringX[x-1]; else alignment[j][0] = -1; alignment[j][1] = stringY[y-1]; } } } } for(int k=0; k