动态规划——edit-distance 计算字符串的相似度

题目描述

求两个字符串的编辑距离:

具体操作方法为:

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

比如,对于“abcd”和"abcde"可以认为最少需要通过增加/减少一个'e'得到,则编辑距离为1。


思路:

若第一个字符是相同的,则考虑两个字符串从第二个字符开始的相似距离即可;

若第一个字符不同,可以选择的方法有:

1.删除A串第一个字符,然后计算A[2,.....lenA]和B[1,......lenB]的距离;

2.删除B串第一个字符,然后计算A[1,.....lenA]和B[2,......lenB]的距离;

3.修改A串的第一个字符为B串的第一个字符,然后计算A[2,.....lenA]和B[2,......lenB]的距离;

4.修改B串的第一个字符为A串的第一个字符,然后计算A[2,.....lenA]和B[2,......lenB]的距离;

5.增加B串的第一个字符到A串第一个字符之前,然后计算A[1,.....lenA]和B[2,......lenB]的距离;

6.增加A串的第一个字符到B串第一个字符之前,然后计算A[2,.....lenA]和B[1,......lenB]的距离;


可以看出都是:

1.一步操作后,再将A[2,.....lenA]和B[1,......lenB]变为相同的字符串;

2.一步操作后,再将A[1,.....lenA]和B[2,......lenB]变为相同的字符串;

3.一步操作后,再将A[2,.....lenA]和B[2,......lenB]变为相同的字符串;


递归程序:

public class Solution {
   public int minDistance(String word1, String word2) {  
        if(word1.length() == 0)//递归边界时的情况;  
                return word2.length();   
        if(word2.length() == 0)  
                return word1.length();  
          
        if(word1.charAt(0) == word2.charAt(0))  
            return minDistance(word1.substring(1),word2.substring(1));  
          
            int a=minDistance(word1.substring(1),word2.substring(1));  
            int b=minDistance(word1.substring(1),word2);  
            int c=minDistance(word1,word2.substring(1));  
          
        return min(a,b,c)+1;  
    }   
    public int min(int a,int b,int c)  
            {  
            int min=a<b?a:b;  
            return min<c?min:c;  
        }  
}
DP:

如果我们用 i 表示当前字符串 A 的下标,j 表示当前字符串 B 的下标。 如果我们用d[i, j] 来表示A[1, ... , i] B[1, ... , j] 之间的最少编辑操作数。那么我们会有以下发现:

1. d[0, j] = j;

2. d[i, 0] = i;

3. d[i, j] = d[i-1, j - 1] if A[i] == B[j]

4. d[i, j] = min(d[i-1, j - 1], d[i, j - 1], d[i-1, j]) + 1  if A[i] != B[j]

找出最小编辑操作数,从底自上判断

public class Solution {
    public int minDistance(String s1, String s2) {
       //dp[i][j]表示s1长为i,s2长为j时的编辑距离;
        int[][] dp=new int[s1.length()+1][s2.length()+1];
        //S1长度为0时,返回s2的长度;
        for(int i=0;i<=s1.length();i++)
            {
            dp[i][0]=i;
        }
        //s2长度为0时,返回s1的长度;
        for(int j=0;j<=s2.length();j++)
            {
            dp[0][j]=j;
        }
        //一般情况
        for(int i=1;i<=s1.length();i++)
            {            
            for(int j=1;j<=s2.length();j++)
                {
                //当s1第i个字符和s2第j个字符相同时:
                if(s1.charAt(i-1) == s2.charAt(j-1))
                    {
                    dp[i][j]=dp[i-1][j-1];
                }
                //当s1第i个字符和s2第j个字符不同时:
                else
                    {
                    //dp[i-1][j-1]为s1的第i个字符变换为s2的第j个字符或者s2变换的情况;
                    //dp[i-1][j]为删除或插入的情况;
                    dp[i][j]=min(dp[i-1][j-1],dp[i-1][j],dp[i][j-1])+1;
                }
            }
        }
        return dp[s1.length()][s2.length()];
    }
    public int min(int a,int b,int c)
        {
        int min=a<b?a:b;
        return min<c?min:c;
    }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值