java 编辑距离类问题编辑距离

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 编辑距离类问题编辑距离相关的知识,希望对你有一定的参考价值。

pubilc int minDistance(String word1,String word2){
    int m = word1.length(),n=word2.length();
    int[][] memory = new int[m][n];//保存计算过的结果,实际就是记忆化搜索
    return helper(word1,0,word2,0,memory);

}
public int helper(String word1,int i,String word2,int j,int[][] memory){
    if(i==word1.length()) return (int)word2.length()-j;
    if(j==word2.length()) return (int)word1.length()-i;
    if(memory[i][j > 0]) return memory[i][j];
    int res = 0;
    if(word1[i]==word2[j]){
        memory[i][j]=helper(word1,i+1,word2,j+1,memory);
        return memory[i][j];
    }else{
        int insert_try = helper(word1,i,word2,j+1,memory);

        int delete_try = helper(word1,i+1,word2,j,memory);
        int replace_try = helper(word1,i+1,word2,j+1,memory);//三种操作在每一个位置都试一试,相当于三叉树搜索,会有重复搜索所以用数组来保存中间计算结果值
        res = min(insert_try,min(delete_try,replace_try))+1;
        memory[i][j]=res;
        return res;
    }
}
//这种先写递归然后发现实际是多叉树搜索问题,然后用记忆化数组来存储中间计算结果值优化时间的方法就是记忆化搜索问题,但是记忆化搜索和DP是相反的过程,两者不同。
//DP是从下到上,记忆化搜索是从上到下。记忆化搜索是从全局到子问题的计算,计算结果保存在数组中,如果另一个分支计算时发现已经计算过了则直接返回该中间结果。
//而DP则是先计算最小的子问题,然后逐步扩大子问题的域,扩大的过程中用到了子问题计算的结果,最后达到原问题的规模来得到结果。
//DP方法,类似于0-1背包问题。建立一个DP数组dp[m+1][n+1],dp[i][j]表示第一个字符串到i位置和第二个字符串到j位置为止最小的编辑距离。根据二维数组DP的套路,会先初始化数组边界值然后再往后依据之前计算的值来计算大的子问题的值。实例:
  Ø a b c d
Ø 0 1 2 3 4
b 1 1 1 2 3
b 2 2 1 2 3
c 3 3 2 1 2
//通过这种实例观察,dp[i][j],如果s1[i]=s2[j]则dp[i][j]=dp[i-1][j-1],而如果不相等则dp[i][j]的值就是该位置的左,左上,上这三个值的最小值加1,这就是递推公式。
//所以动态规划这里有一个dp数组,而上面的记忆化搜索也有个dp数组,两个数组是相同的,但是计算过程不同。DP函数调用顺序是从左上角往右下角走来调用函数,而记忆化搜索是从右下角调用函数,由于子问题还没计算导致递归调用从而是从右下角往左上角走调用。
//0-1背包问题也是DP这种从左上角往右下角走调用函数的过程。所以DP不是个递归调用过程,在DP函数不会出现递归调用,否则说明顺序反了,而记忆化搜索是个递归调用过程。
public int minEditDis(String s1,String s2){
  int m = s1.length();
  int n = s2.length();
  int[][] dp = new int[m+1][n+1];
  for(int i=0; i<= m; i++){
    for(int j = 0 ; j <=n; j++){
      if(i==0) dp[i][j]=j;
      else if(j==0) dp[i][j]=i;
      else{
        if(s1.charAt(i-1)==s2.charAt(j-1)) dp[i][j]=dp[i-1][j-1];
        else dp[i][j]=1+min(dp[i-1][j],dp[i-1][j-1],dp[i][j-1]);
      }
    }
  }
  return dp[m][n];
}
//所以应用动态规划算法的题目,实际背后隐藏着与其对应的记忆化搜索过程,而记忆化搜索实际上是多叉树的分支搜索过程,树中每个非叶子结点都是一个数组或字符串。也就是说如果发现某个问题可以总结成多叉树的搜索问题,那就说明可以用记忆化数组来优化其时间,而能够记忆化数组的问题说明如果将这种递归调用函数的逻辑顺序反过来从最小的子问题出现逐步扩大问题的域,就可以得到动态规划算法。这些都是相通的。
//判断两个字符串是否编辑距离为1.分三种情况讨论:两个长度大于1则false,等于1则找到从哪个位置不相等然后比较后面的字符串是否相等,等于0则比较是否只有一个字符不相等。
public boolean oneEditDis(String s1,String s2){
  String s = s1.length()>s2.length()?s1:s2;
  String t = s1.length()>s2.length()?s2:s1;
  if(s.length()-t.length() >= 2) return false;
  else if(s.length()-t.length()==1){
    for(int i = 0; i < s.length() ; i++){
      if(s.charAt(i)!=t.charAt(i)) return s.substring(i+1)==t.substring(i);
    }
  }else{
    int cnt = 0;
    for(int i = 0 ; i < s.length(); i++){
      if(s.charAt(i)!=t.charAt(i)) cnt++;
    return cnt==1;
    }
  }
}

以上是关于java 编辑距离类问题编辑距离的主要内容,如果未能解决你的问题,请参考以下文章

java 72.编辑距离(#)。java

java 72.编辑距离(#)。java

java 72.编辑距离(#)。java

java 72.编辑距离(#)。java

java 72.编辑距离(#)。java

java 72.编辑距离(#)。java