/*
Edit Distance problem:
What is the minimum number of insertions, deletions, substitutions 
on P[1..m] that will yield T[1..n]?
*/

int min(int a, int b, int c);

#include <string>
using namespace std;

#if 1
// Basic recursive bruteforce 

int editDist(string P, int m, string T, int n) {

	// base cases
	if (m == 0) return n; // n inserts needed to make T out of P.
	if (n == 0) return m; // m deletes needed to make T out of P.

	int sub, ins, del;

	// Consider the edit to get the last characters matching.
	// It is one of 4 things.
	// (a) fortunately, they already match.
	// (b) do a substitution of P's last char to match T's last.
	// (c) insert a new char on end of P that matches last char of T.
	// (d) delete last char on end of P to complete the match with T.

	if (P[m] == T[n]) /*no*/sub = editDist(P, m-1, T, n-1); // case (a)

	if (P[m] != T[n]) sub = 1 + editDist(P, m-1, T, n-1); // case (b)

	ins = 1 + editDist(P, m, T, n-1); // case (c)

	del = 1 + editDist(P, m-1, T, n); // case (d)

	return min(sub, ins, del);
}

#else
// Dynamic Programming
int editDist(string P, int m, string T, int n) {
	int* M = new int[(m+1)*(n+1)]; // array with 0-based indexing
	int w = n+1;// width of table.  The (i,j) entry is M[i*w + j].

    // M[i*w + j] is the edit distance from P[1..i] to T[1..j]
	for (int i = 0; i <= m; ++i) // initialize first entry in i-th row.
		M[i*w + 0] = i; // i deletions makes P go to T = nothing
	for (int j = 0; j <= n; ++j) // initialize first entry in j-th column.
		M[0*w + j] = j; // j insertions makes P go to T from nothing.

	// now fill in row by row
	for (int i = 1; i <= m; ++i)
		for (int j = 1; j <= n; ++j) {
			int sub, ins, del;

			if (P[i] == T[j]) 
				/*no*/sub = M[(i-1)*w +(j-1)]; // nosub (case a)
			if (P[i] != T[j]) 
				sub = 1 + M[(i-1)*w +(j-1)]; // sub (case b)
			ins = 1 + M[i*w + j-1]; // ins (case c)
			del = 1 + M[(i-1)*w + j]; // del (case d)

			M[i*w + j] = min(sub, ins, del);
		}
	return M[m*w + n];
}
#endif

int min(int a, int b, int c) {
	int ans = a;
	if (b < ans) ans = b;
	if (c < ans) ans = c;
	return ans;
}
