【哈希、动态规划】Edit Distance

来源:互联网 发布:java 反射实现接口 编辑:程序博客网 时间:2024/06/14 07:05

题目:leetcode

Edit Distance

 

Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)

You have the following 3 operations permitted on a word:

a) Insert a character
b) Delete a character
c) Replace a character


方法一:记忆化递归

每次递归时,都进行三种操作。注意:1、插入操作的运行条件需要重点留意。2、自定义的node类型的哈希函数应该设置得好一点,这里使用c++默认哈希函数。

class node{  public:  string w1;  string w2;  node(string a,string b):w1(a),w2(b){}  bool operator==(const node &rch)const  {      if( (rch.w1==w1 && rch.w2==w2) || (rch.w2==w1 && rch.w1==w2) )      return true;      else      return false;  }  };struct hash_node{size_t operator()(const node &r)const{std::hash<std::string> h;size_t n1 = h(r.w1);size_t n2 = h(r.w2);return n1^n2;//return hash<char>()(r.w1[0]) ^ hash<char>()(r.w2[0]);}};class Solution {public:    int minDistance(string word1, string word2) {        if(word1.empty())        return word2.size();        if(word2.empty())        return word1.size();                //删除相同的前缀        if(word1[0]==word2[0])        {            int i=0;            for(;i<word1.size() && i<word2.size() ;i++)            {                if(word1[i]!=word2[i])                break;            }            if(i==word1.size() || i==word2.size())            {                int size1=word1.size(),size2=word2.size();                return abs(size1-size2);            }            word1.erase(word1.begin(),word1.begin()+i);            word2.erase(word2.begin(),word2.begin()+i);        }                unordered_map<node,int,hash_node> table;        size_t up=word1.size()+word2.size();//该参数是Insert a character的上限        return minDistance_core(word1,word2,table,up);    }        int minDistance_core(string w1, string w2,unordered_map<node,int,hash_node> &table,size_t up)     {        if(w1.empty())        return w2.size();        if(w2.empty())        return w1.size();                 node a(w1,w2);         if(table.count(a)>0)         return table[a];                //删除相同的前缀        if(w1[0]==w2[0])        {            int i=0;            for(;i<w1.size() && i<w2.size() ;i++)            {                if(w1[i]!=w2[i])                break;            }            if(i==w1.size() || i==w2.size())            {                int size1=w1.size(),size2=w2.size();                int res= abs(size1-size2);                 table[a]=res;                 return res;            }            w1.erase(w1.begin(),w1.begin()+i);            w2.erase(w2.begin(),w2.begin()+i);        }        //Replace a character        string s1=w1.substr(1,w1.size()-1);        string s2=w2.substr(1,w2.size()-1);        int res1=1+minDistance_core(s1,s2,table,up);        //Insert a character        int  res2=0x7fffffff;        bool flag=false;        for(auto &i:w2)        {            if(i==w1[0])            {                flag=true;                break;            }        }        //只有当w1的长度小于上限,且w1[0]在w2中有出现,才进行插入操作        if(w1.size()<up && flag)            res2=1+minDistance_core(w1,s2,table,up);        //Delete a character        int res3=1+minDistance_core(s1,w2,table,up);                int res=min(res1,res2);        res=min(res,res3);                       table[a]=res;        return res;    }};

方法二:动态规划

用f[i][j]表示A[0,i]和B[0,j]之间的最小编辑距离。先初始化i==0和j==0的情况,然后f[i][j]=1+min(f[i-1][j],f[i][j-1],f[i-1][j-1]).

 int minDistance(string word1, string word2) {        if(word1.empty())        return word2.size();        if(word2.empty())        return word1.size();                //删除相同的前缀        if(word1[0]==word2[0])        {            int i=1;            for(;i<word1.size() && i<word2.size() ;i++)            {                if(word1[i]!=word2[i])                break;            }            if(i==word1.size() || i==word2.size())            {                int size1=word1.size(),size2=word2.size();                return abs(size1-size2);            }            word1.erase(word1.begin(),word1.begin()+i);            word2.erase(word2.begin(),word2.begin()+i);        }                vector<vector<int>> f(word1.size(),vector<int>(word2.size(),0));        bool same=false;        for(int i=0;i<word1.size();i++)        {            if(same)            {                f[i][0]=f[i-1][0]+1;                continue;            }            if(word1[i]==word2[0])            {                same=true;                f[i][0]=i;            }            else            {                 f[i][0]=i+1;            }        }        same=false;         for(int j=0;j<word2.size();j++)        {            if(same)            {                f[0][j]=f[0][j-1]+1;                continue;            }            if(word2[j]==word1[0])            {                same=true;                f[0][j]=j;            }            else            {                 f[0][j]=j+1;            }        }                  for(int i=1;i<word1.size();i++)          {               for(int j=1;j<word2.size();j++)               {                   if(word1[i]==word2[j])                   f[i][j]=f[i-1][j-1];                   else                   {                       int tmp=min(f[i-1][j],f[i][j-1]);                       tmp=min(tmp,f[i-1][j-1]);                       f[i][j]=tmp+1;                   }               }                         }               return f.back().back();    }



0 0