|
|
|
|
|
(Named after Vladimir Levenshtein)
|
|
|
|
T( x, y, n, m ) { // I will 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 + 0; // 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(String x, String y, int i, int j) { int sol1, sol2, sol3, MySol; /* --------------------------- Base cases --------------------------- */ if ( i == 0 ) // x = "" { return(j); // Uses j insertions } if ( j == 0 ) // y = "" { return(i); // Uses i deletions... } /* -------------------------------------------------- The other cases.... -------------------------------------------------- */ if ( x.charAt(i-1) == y.charAt(j-1) ) { /* ------------------------ Divide step ------------------------ */ sol1 = T(i-1, j-1); /* --------------------------------------- Conquer: solve original problem using solution from smaller problems --------------------------------------- */ MySol = sol1; // No edit necessary... return(MySol); } 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 ) MySol = sol1; if ( sol2 <= sol1 && sol2 <= sol3 ) MySol = sol3; if ( sol3 <= sol1 && sol3 <= sol2 ) MySol = sol3; return( MySol ); } } |
How to run the program:
|
Sample output:
String x = man String y = moon Min. Edit Distance = 2 |
|
|
Let's try to do that now....
int MinEditDistance(String x, String y, int i, int j) { int sol1, sol2, sol3, MySol; /* --------------------------- Base cases --------------------------- */ if ( i == 0 ) // x = "" { return(j); // Uses j insertions } if ( j == 0 ) // y = "" { return(i); // Uses i deletions... } /* -------------------------------------------------- The other cases.... -------------------------------------------------- */ if ( x.charAt(i-1) == y.charAt(j-1) ) { /* ------------------------ Divide step ------------------------ */ sol1 = T(i-1, j-1); /* --------------------------------------- Conquer: solve original problem using solution from smaller problems --------------------------------------- */ MySol = sol1; // No edit necessary... return(MySol); } 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 ) MySol = sol1; if ( sol2 <= sol1 && sol2 <= sol3 ) MySol = sol3; if ( sol3 <= sol1 && sol3 <= sol2 ) MySol = sol3; return( MySol ); } } |
|
|
|
so you avoid using recursion if we compute the values T[i][j] in the following order:
for ( i = 0; i < x.length()+1; i++ ) for ( j = 0; j < y.length()+1; j++ ) { compute T[i][j] according to the recursive algorithm } |
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)
|