|
|
|
|
|
(Named after Vladimir Levenshtein)
|
|
|
|
T( x, y, n, m ) { // I wull ignore the base cases for now.... /* ================================== The divide and conquer procedure =================================== */ if ( last char in x == last char in y ) { /* ------------------------------------ Last char's in strings are equal ------------------------------------ */ sol1 = T( x, y, n-1, m-1 ); // Solve smaller problem MySol = sol1 + 1; // Use solution to solve my problem return(MySol); } else { /* ------------------------------------------- Last char's in strings are NOT equal Divide: Try: delete, insert or substitute ------------------------------------------- */ sol1 = T(x, y, i-1, j); // Subproblem when edit oper is delete sol2 = T(x, y, i, j-1); // Subproblem when edit oper is insert sol3 = T(x, y, i-1, j-1); // Subproblem when edit oper is substit /* ------------------------------------------- Conquer: solve original problem using solution from smaller problems ------------------------------------------- */ MySol1 = sol1 + 1; // Cost of my solution if I used delete MySol2 = sol2 + 1; // Cost of my solution if I used insert MySol3 = sol3 + 1; // Cost of my solution if I usde substitute MySol = min( MySol1, MySol2, MySol3 ); return(MySol); } } |
|
T(0, m) = m (we need to insert m characters into x to get y) T(n, 0) = n (we need to delete n characters from x to get y) |
int MinEditDistance(A, B, i, j) { int sol1, sol2, sol3; /* --------------------------- Base cases --------------------------- */ if ( i == 0 ) // x = "" { return(j); // Uses j insertions } if ( j == 0 ) // y = "" { return(i); // Uses i deletions... } /* -------------------------------------------------- The other cases.... -------------------------------------------------- */ if ( A[i] == B[j] ) { /* ------------------------ Divide step ------------------------ */ sol1 = T(i-1, j-1); /* --------------------------------------- Conquer: solve original problem using solution from smaller problems --------------------------------------- */ return(sol1); } else { /* ------------------------ Divide step ------------------------ */ sol1 = T(i-1, j); // Try delete step as last sol2 = T(i, j-1); // Try insert step as last sol3 = T(i-1, j-1); // Try replace step as last /* --------------------------------------- Conquer: solve original problem using solution from smaller problems --------------------------------------- */ sol1 = sol1 + 1; sol2 = sol2 + 1; sol3 = sol3 + 1; /* --------------------------------------- Return min(sol1, sol2, sol3) --------------------------------------- */ if ( sol1 <= sol2 && sol1 <= sol3 ) return(sol1); if ( sol2 <= sol1 && sol2 <= sol3 ) return(sol2); if ( sol3 <= sol1 && sol3 <= sol2 ) return(sol3); } return(0); // This dummy statement is needed to Java compiler happy... } |
How to run the program:
|
Sample output:
String x = man String y = moon Min. Edit Distance = 2 |
The added code is highlighted in RED:
static int min = Integer.MAX_VALUE; static String ans = ""; static int T(String x, String y, int i, int j, int n, String s) { int sol1, sol2, sol3; /* --------------------------- Base cases --------------------------- */ if ( i == 0 ) { if ( n + j <= min ) { min = n + j; // Remember the current min if ( j > 0 ) ans = s + j + " ins()"; else ans = s; } return(j); } if ( j == 0 ) { if ( n + i <= min ) { min = n + i; // Remember the current min if ( i > 0 ) ans = s + i + " del()"; else ans = s; } return(i); } /* =========================================== The other cases =========================================== */ if ( x.charAt(i-1) == y.charAt(j-1) ) { sol1 = T(x, y, i-1, j-1, n, s /* No addition edit ops */); return(sol1); } else { /* ------------------------ Divide step ------------------------ */ sol1 = T(x, y, i-1, j, n+1, s + "del(" + (i-1) + ");"); // Try delete step as last sol2 = T(x, y, i, j-1, n+1, s + "ins("+ y.charAt(j-1)+"," + (i-1) + ");"); // Try insert step as last sol3 = T(x, y, i-1, j-1, n+1, s + "sub("+ x.charAt(i-1) + "->"+ y.charAt(j-1)+"," + (i-1) + ");"); // Try replace step as last /* --------------------------------------- Conquer: solve original problem using solution from smaller problems --------------------------------------- */ sol1 = sol1 + 1; sol2 = sol2 + 1; sol3 = sol3 + 1; if ( sol1 <= sol2 && sol1 <= sol3 ) return(sol1); if ( sol2 <= sol1 && sol2 <= sol3 ) return(sol2); if ( sol3 <= sol1 && sol3 <= sol2 ) return(sol3); } return(0); // To please the stupid Java compiler } |
|
static int[][] T; // Store the result of T(i,j) static int compT(String x, String y) { int sol1, sol2, sol3; int i, j; /* --------------------------- Base cases --------------------------- */ for ( i = 0; i <= x.length(); i++ ) T[i][0] = i; for ( j = 0; j <= y.length(); j++ ) T[0][j] = j; /* ------------------------ The other cases... ------------------------ */ for ( i = 1; i <= x.length(); i++ ) for ( j = 1; j <= y.length(); j++ ) { if ( x.charAt(i-1) == y.charAt(j-1) ) { sol1 = T[i-1][j-1]; T[i][j] = sol1; } else { /* ------------------------ Divide step ------------------------ */ sol1 = T[i-1][j]; // Try delete step as last step sol2 = T[i][j-1]; // Try insert step as last step sol3 = T[i-1][j-1]; // Try replace step as last step /* --------------------------------------- Conquer: solve original problem using solution from smaller problems --------------------------------------- */ sol1 = sol1 + 1; sol2 = sol2 + 1; sol3 = sol3 + 1; if ( sol1 <= sol2 && sol1 <= sol3 ) T[i][j] = sol1; if ( sol2 <= sol1 && sol2 <= sol3 ) T[i][j] = sol2; if ( sol3 <= sol1 && sol3 <= sol2 ) T[i][j] = sol3; } } /* ----------------------------- Return the final answer... ----------------------------- */ return(T[x.length()][y.length()]); } |
|
Each subproblem can be solved with O(1) time (find the minimum of 3 numbers)
|