|
|
|
|
|
(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)
|