Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Edit distance - With memoization

I'm trying to do the edit distance problem, but cache the results so I don't repeat calls. It worked before I tried to store subproblems in a map, but now it stops working. For the call I make, comparing "thou shalt not" and "you should not", it returns 1. Obviously incorrect, but why?

using namespace std;
int counter = 0;

int match(char c1, char c2){
  c1 == c2 ? 0 : 1;
}

int edit_distance(string s1, string s2,map<pair<string,string>, int>& memo){
  if(memo[make_pair(s1,s2)])
    return memo[make_pair(s1,s2)];
  int i = s1.size();
  int j = s2.size();

  if(s1.empty())
    return memo[make_pair(s1,s2)] = 1 + j;
  if(s2.empty())
    return memo[make_pair(s1,s2)] = 1 + i;

  int opt[3];

  opt[0] = edit_distance(s1.substr(1), s2.substr(1),memo) + match(s1[i-1],s2[j-1]);
  opt[1] = edit_distance(s1.substr(1), s2,memo) + 1;
  opt[2] = edit_distance(s1, s2.substr(1),memo) + 1;

  int min = opt[0];
  for(int i = 1; i < 3; i++){
    if(opt[i] < min)
      min = opt[i];
  }
  memo[ make_pair(s1,s2) ] = min;
  return min;
}

int edit_distance_driver(string s1, string s2){
  map<pair<string,string>,int> memo;
  return edit_distance(s1, s2, memo);
}

int main(){
  cout << edit_distance_driver("thou shalt not","you should not") << endl;
}
like image 946
ordinary Avatar asked Oct 02 '22 14:10

ordinary


1 Answers

The problem is here:

opt[0] = edit_distance(s1.substr(1), s2.substr(1),memo) + match(s1[i-1],s2[j-1]);

You recurse without the first characters, but you check the last characters.

You should instead check the first characters, so it should be:

opt[0] = edit_distance(s1.substr(1), s2.substr(1),memo) + match(s1[0],s2[0]);

And obviously match should return something:

int match(char c1, char c2){
  return c1 == c2 ? 0 : 1;
}

Then your code prints 6 for those strings.

like image 114
Bernhard Barker Avatar answered Oct 05 '22 23:10

Bernhard Barker