最长公共子序列(LCS)及其应用(密码脱落)
给定两个 string 字符串,找出他们的最长公共子序列(Longest Common Sequence,LCS)。
例如 string A = “BDCABA“,string B = ”ABCBDAB“,他们的LCS = 4。
求最长公共子序列的经典方法属于一种动态规划(Dynamic Programming,DP)。
而动态规划的两个基本要素为:① 最优子结构 ② 重叠子问题
① 最优子结构
设 X = x1 x2 … xn Y = y1 y2 … ym
若 xn == ym,说明该元素一定存在于LCS中,
故只要求 LCS(Xn-1,ym-1),这是一个最优的子问题。
若 xn != ym,则继续分类缩小问题的范围。
故只要求 max{LCS(Xn-1,Ym),LCS(Xn,Ym-1)} 即可。
② 重复子问题
LCS(X,Y):LCS(Xn-1,Ym-1),LCS(Xn-1,Ym),LCS(Xn,Ym-1)
LCS(Xn-1,Ym):LCS(Xn-2,Ym-1),LCS(Xn-2,Ym),LCS(Xn-1,Ym-1)
……
如图会有很多重复的子问题,若用递归做时间会以指数增长。
用 dp 做的直接进行“查表”即可。
综上:
参考代码:
int LCS(string str1, string str2){
// 初始化第一行和第一列
for(int i = 0; i <= len1; i++){
dp[i][0] = 0;
}
for(int i = 0; i <= len2; i++){
dp[0][i] = 0;
}
// 构建dp数组
for(int i = 1; i <= len1; i++){
for(int j = 1; j <= len2; j++){