📜  生成长度为 k 的最长公共子序列的最小成本(1)

📅  最后修改于: 2023-12-03 15:40:52.113000             🧑  作者: Mango

生成长度为 k 的最长公共子序列的最小成本

什么是最长公共子序列?

最长公共子序列(Longest Common Subsequence,简称LCS)是指是指在多个序列中都出现的,长度最长的子序列。

比如说,对于字符串X=“BDCABA”和字符串Y=“ABCBDAB”,它们的最长公共子序列为“BCBA”,长度为4。

如何生成长度为 k 的最长公共子序列?
动态规划

常用的做法是动态规划。我们设f[i,j]表示字符串X前i个字符和字符串Y前j个字符的最长公共子序列长度。

这样,我们就可以用下面的递推公式求得f[i,j]:

f[i,j] = 0                            (i=0或j=0)
       = f[i-1, j-1] + 1              (X[i] = Y[j])
       = max(f[i, j-1], f[i-1, j])    (X[i] != Y[j])

最终,我们就可以通过f[k,k]来找到长度为k的最长公共子序列了。

最小成本

但是,我们还需要考虑成本问题。如果我们在计算f[i,j]的时候,X[i] = Y[j],那么我们可以认为我们获取了一个公共字符,成本为0。如果X[i] != Y[j],那么我们需要做出选择,要么选择保留字符串X,要么选择保留字符串Y,这样就需要产生成本,成本为1。

因此,我们需要对上面的递推公式进行修改,得到更新后的递推公式:

f[i,j] = 0                            (i=0或j=0)
       = f[i-1, j-1] + cost(i,j)     (X[i] = Y[j])
       = max(f[i, j-1], f[i-1, j])    (X[i] != Y[j])

其中,cost(i,j)表示X[i] = Y[j]的情况下产生的成本。

代码实现

下面是一个使用Python实现上述算法的范例代码:

def lcs_with_cost(X, Y, k):
    m, n = len(X), len(Y)
    if max(m, n) < k:
        return 0
  
    # 初始化f数组
    f = [[0] * (n + 1) for i in range(m + 1)]
    for i in range(1, m+1):
        for j in range(1, n+1):
            # 根据情况更新f数组
            if X[i-1] == Y[j-1]:
                f[i][j] = f[i-1][j-1] + (0 if f[i-1][j-1] < k else 1) # 判断是否需要产生成本
            else:
                f[i][j] = max(f[i][j-1], f[i-1][j])

    return f[m][n]

使用以上代码,我们可以很方便地计算出长度为k的最长公共子序列的最小成本了。