动态规划 最长公共子序列&最小编辑距离

https://leetcode-cn.com/problems/edit-distance/
https://leetcode-cn.com/problems/edit-distance/solution/zi-di-xiang-shang-he-zi-ding-xiang-xia-by-powcai-3/


最长公共子序列

描述

令 A = a1a2…an,B = b1b2…bn
令 L[ i , j ] 表示 a1a2…ai 和 b1b2…bj 的最长公共子序列的长度

当 A[i] == B[i],L[ i , j ] = L[ i-1 , j-1 ] + 1
当 A[i] != B[i],L[ i , j ] = max{ L[ i-1 , j ] , L[ i , j-1 ] }

eg:
A = horse,B = ros
i为2,j为2时,o == o,L[ ho , ro ] = L[ h , r ] + 1
i为3,j为3时,r != s,L[ hor , ros ] = max{ L[ ho , ros ] , L[ hor , ro ] }

例子

开始时,第一行、第一列均为0
箭头数值记录来源(后续可根据箭头方向恢复出最长公共子序列)

填完是这样的

可以根据箭头方向恢复出最长公共子序列(不唯一)

java实现

public static int LCS(String word1, String word2) {
	
    int[][] maxSub = new int[word1.length()+1][word2.length()+1];
    
	for(int i=1;i<word1.length()+1;i++) {
		for(int j=1;j<word2.length()+1;j++) {
			if(word1.charAt(i-1)==word2.charAt(j-1)) {
				maxSub[i][j] = maxSub[i-1][j-1] + 1;
			}else {
				maxSub[i][j] = Math.max(maxSub[i-1][j], maxSub[i][j-1]);
			}
		}
	}
    
	return maxSub[word1.length()][word2.length()];
}

最短编辑距离

描述

令 A = a1a2…an,B = b1b2…bn
令 L[ i , j ] 表示 a1a2…ai 和 b1b2…bj 的最短编辑距离

当 A[i] == B[i],L[ i , j ] = L[ i-1 , j-1 ]
当 A[i] != B[i],L[ i , j ] = min{ L[ i-1 , j-1 ] , L[ i-1 , j ] , L[ i , j-1 ] } + 1
其中,L[ i-1 , j-1 ] 代表替换操作,L[ i-1 , j ] 代表删除操作,L[ i , j-1 ] 代表插入操作

eg:
A = horse,B = ros
i为2,j为2时,o == o,L[ ho , ro ] = L[ h , r ],无需继续编辑
i为3,j为3时,r != s,L[ hor , ros ] = min{ L[ ho , ro ] , L[ ho , ros ] , L[ hor , ro ] } + 1
L[ ho , ro ] + 1 代表,在ho已经编辑成ro之后,将r替换成s
L[ ho , ros ] + 1 代表,在ho已经编辑成ros之后,将r删除
L[ hor , ro ] + 1 代表,在hor已经编辑成ro之后,插入s

例子

开始时,第一行为行序号,第一列为列序号

填完是这样的

编辑过程

java实现

public static int minDistance(String word1, String word2) {
	
    int[][] minEdit = new int[word1.length()+1][word2.length()+1];
    
    for(int i=1;i<word1.length()+1;i++) {
    	minEdit[i][0] = i;
    }
    for(int i=1;i<word2.length()+1;i++) {
    	minEdit[0][i] = i;
    }
    
	for(int i=1;i<word1.length()+1;i++) {
		for(int j=1;j<word2.length()+1;j++) {
			if(word1.charAt(i-1)==word2.charAt(j-1)) {
				minEdit[i][j] = minEdit[i-1][j-1];
			}else {
				int min = Math.min(minEdit[i-1][j], minEdit[i][j-1]);
				min = Math.min(min, minEdit[i-1][j-1]);
				minEdit[i][j] = min+1;
			}
		}
	}	
	
	return minEdit[word1.length()][word2.length()];
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章