// Name(s): // Email id(s): import java.util.*; import java.awt.*; public class EditDistance { public static void main( String[] args ) { Solution solution = solve( "TAAGGTCA", "AACAGTTACC" ); System.out.println( solution ); System.out.println( solution.validate() ); } public static Solution solve ( String s1, String s2 ) { int n1 = s1.length(); int n2 = s2.length(); int[][] optimal = new int [ n1+1 ] [ n2+1 ]; for ( int i = 0; i < n1; ++i ) { optimal[ i ][ n2 ] = 2 * ( n1 - i ); } for ( int j = 0; j < n2; ++j ) { optimal[ n1 ][ j ] = 2 * ( n2 - j ); } for ( int i = n1 - 1; 0 <= i; --i ) { for ( int j = n2 - 1; 0 <= j; --j ) { int[] poss = new int[ 3 ]; poss[ 0 ] = optimal[ i+1 ] [ j+1 ] + ( s1.charAt( i ) == s2.charAt( j ) ? 0 : 1 ); poss[ 1 ] = optimal[ i ] [ j+1 ] + 2; poss[ 2 ] = optimal[ i+1 ] [ j ] + 2; Arrays.sort( poss ); optimal[ i ][ j ] = poss[ 0 ]; } } String t1 = ""; String t2 = ""; String penalty = ""; int j = 0; int i = 0; int k = 0; while ( j < s2.length() && i < s1.length() ) { if ( s1.charAt(i) == s2.charAt(j) && optimal[ i ][ j ] == optimal[ i+1 ][ j+1 ]) { t1 += s1.charAt(i); t2 += s2.charAt(j); penalty += 0; ++i; ++j; } else if ( ( optimal[ i ][ j ] - optimal[ i+1 ][ j+1 ] ) == 1 ) { t1 += s1.charAt(i); t2 += s2.charAt(j); penalty += 1; ++i; ++j; } else if ( optimal[ i ][ j ] == optimal[ i+1 ][ j ] + 2 ) { t1 += s1.charAt(i); t2 += "-"; penalty += 2; ++i; } else if ( optimal[ i ][ j ] == optimal[ i ][ j+1 ] + 2 ) { t1 += "-"; t2 += s2.charAt(j); penalty += 2; ++j; } } while ( i < s1.length() ) { t1 += s1.charAt( i ) ; t2 += "-"; penalty += 2; ++i; } while ( j < s2.length() ) { t1 += "-" ; t2 += s2.charAt( j ); penalty += 2; ++j; } return new Solution(s1, s2, optimal, t1, t2, penalty); } } class Solution { String s1; String s2; int[][] optimal; String t1; String t2; String penalty; public Solution(String s1, String s2, int[][] optimal, String t1, String t2, String penalty) { this.s1 = s1; this.s2 = s2; this.optimal = optimal; this.t1 = t1; this.t2 = t2; this.penalty = penalty; } public String toString() { String result = ""; for (int i = 0; i < optimal.length; ++i ) { for (int j = 0; j < optimal[i].length; ++j ) { result += String.format( "%3d ", optimal[i][j] ); } result += "\n"; } result += "\n"; result += s1 + "\n" + s2 + "\n\n" + t1 + "\n" + t2 + "\n" + penalty; return result; } public boolean validate() { int n = t1.length(); // check to see if solution is nonsensible if ( ( n != t2.length() ) || ( n != penalty.length() ) ) { System.out.println( "Penalty and edit strings have conflicting sizes" ); return false; } // does t1 and t2 track s1 and s2 for ( int k = 0, i = 0, j = 0; i < s1.length(); ++k ) { char b = s1.charAt(i); char c = t1.charAt(j); char d = t2.charAt(k); if ( ( c != '-' ) && ( b == c ) ) { ++i; ++j; } else if ( ( c == '-' ) ) { ++j; } else { System.out.println( "Edits nonsensible for first string" ); return false; } } for ( int k = 0, i = 0, j = 0; j < s2.length(); ++k ) { char b = s2.charAt(i); char c = t2.charAt(j); char d = t1.charAt(k); if ( ( c != '-' ) && ( b == c ) ) { ++i; ++j; } else if ( ( c == '-' ) ) { ++j; } else { System.out.println( "Edits nonsensible for second string" ); return false; } } // does penalty make sense int sum = 0; for ( int i = 0; i < n; ++i ) { char c1 = t1.charAt(i); char c2 = t2.charAt(i); char p = penalty.charAt(i); if ( (c1 == c2) && (c1 != '-') && (p == '0' ) ) { sum += 0; continue; } else if ( (c1 != c2) && (p == '1' )) { sum += 1; continue; } else if ( (c1 == '-') && (c2 != '-') && (p == '2') ) { sum += 2; continue; } else if ( (c1 != '-') && (c2 == '-') && (p == '2') ) { sum += 2; continue; } System.out.println( "Penalties do not correspond with edits" ); return false; } // left to check the penalty match the score if ( sum == optimal[0][0] ) { return true; } else { System.out.println( "Penalties do not sum to score" ); return false; } } }