// Arup Guha
// 1/16/04
// Edit Distance example for Programming Team Lecture on Dynamic
// Programming. Both a recursive and DP solution are implemented.

using namespace std;

#include <iostream>

int min(int a, int b, int c);
int strmatch(char *s, char *t, int i, int j);
int strmatchdyn(char *s, char *t, int slen, int tlen);

int main() {

  char word1[50], word2[50];

  // Small Test. Don't enter words longer than 12 or 13 characters for the
  // recursive function though!!!
  cout << "Enter the first word." << endl;
  cin >> word1;
  cout << "Enter the second word." << endl;
  cin >> word2;

  int ans = strmatch(word1, word2, strlen(word1), strlen(word2));
  int ans2 = strmatchdyn(word1, word2, strlen(word1), strlen(word2));
  cout << "Edit Distance is " << ans << endl;
  cout << "Edit Distance Dyn is " << ans2 << endl;

  return 0;

}


// Returns the edit distance of strings s and t which have lengths slen
// and tlen, respectively. Uses Recursion.
int strmatch(char *s, char *t, int i, int j) {

  // Base case: Either string is empty. We must delete all the characters
  // in the other string.
  if (i==0) return j;
  if (j==0) return i;

  // Check if the last characters match. If so, match them up.
  if (s[i-1] == t[j-1])
    return strmatch(s,t,i-1,j-1);

  // Otherwise, we have three options: delete either last character, or
  // switch one of the two characters.
  else
    return 1+min(strmatch(s,t,i,j-1),strmatch(s,t,i-1,j),
		 strmatch(s,t,i-1,j-1));

}

// Returns the edit distance of strings s and t which have lengths slen
// and tlen, respectively. Uses Dynamic Programming.
int strmatchdyn(char *s, char *t, int slen, int tlen) {

  int i,j;

  // Dynamically allocate the DP table.
  int **table;
  table = new int*[slen+1];
  for (i=0; i<slen+1; i++)
    table[i] = new int[tlen+1];

  // Set up data corresponding to the base case in the table.
  for (i=0; i<slen+1; i++)
    table[i][0] = i;
  for (i=0; i<tlen+1; i++)
    table[0][i] = i;

  // Fill in the table from the top left to the bottom right.
  for (i=1; i<slen+1; i++)
    for (j=1; j<tlen+1; j++)

      // Check if the current characters match.
      if (s[i-1]==t[j-1])
        table[i][j] = table[i-1][j-1];

      // Otherwise take the minimum of the three cases outlined in the
      // recursive case.
      else
        table[i][j] = 1+min(table[i-1][j-1],table[i-1][j],table[i][j-1]);

  // This is the entry in the table we need to return.
  return table[slen][tlen];
}

// Returns the minimum value of a, b and c.
int min(int a, int b, int c) {
  if ((a<b) && (a<c))
    return a;
  else if (b<c)
    return b;
  return c;
}
