/*
Edit Distance problem:
What is the minimum number of insertions, deletions, substitutions on P that will yield T?
*/

#include "UDAlgorithms/sequence.h"
typedef sequence<char> seq;

int editDist(seq P, seq T) {
	int m = size(P);
	int n = size(T);

	// 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.

	// initial segments used for subproblems
	seq P1 = subseq(P, 1, m-1);
	seq T1 = subseq(T, 1, n-1);
	
	int sub, nosub, 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.
	sub = nosub = infinity;

	if (P[m] == T[n]) nosub = editDist(P1, T1); // case (a)

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

	ins = editDist(P, T1) + 1; // case (c)

	del = editDist(P1, T) + 1; // case (d)

	return min(sub, nosub, ins, del);


int editDistDP(seq P, seq T) {
	int m = size(P);
	int n = size(T);
	int* T = new int[(m+1)*(n+1)]; // array with 0-based indexing
	int w = n+1;// width of table.  i,j entry is T[i*w + j].

	for (int i = 0; i <= m; ++i) // initialize first entry in i-th row.
		T[i*w + 0] = i;
	for (int j = 0; j <= n; ++j) // initialize first entry in j-th column.
		T[0*w + j] = j;

	// now fill in row by row
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= n; ++j) {
			int entry;
			if (P[i+1] == T[j+1]) // P and T have 1-based indexing.
				entry = T[(i-1)*w +(j-1)]; // nosub (case a)
			else 
				entry = 1 + T[(i-1)*w +(j-1)]; // sub (case b)
			entry = min(entry, 1 + T[(i-1)*w + j]); // ins (case c)
			entry = min(entry, 1 + T[i*w + (j-1)]); // del (case d)
			T[i*w + j] = entry;
		}
	return T[(m+1)*(n+1) - 1];
}
