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