# coding=utf-8 # 计算LCS长度算法 算法 改进 只用 一行 和 一个 额外空间 求得长度 空间复杂度由O(m*n)降低为O(n) # 空间优化。观察状态转移方程,计算的F[i,j]时只和F[i-1,j-1],F[i,j-1],F[i-1,j]三个元素直接相关。 # 仔细分析一下,在递推F[i]这一行的子问题时,只需要知道F[i-1]一行的值和当前计算的F[i,j]的前一个元素的值f[i,j-1]即可,于是空间复杂度由O(m*n)降低为O(n)。 # 核心思想 # 初始化一个长m+1全0的序列base[],一个为0的递推前导front和一个当前计算元素pre(意义上的F[i,j]), # 每次计算完F[i,j]后,front的值更新到base[j-1]上,然后把pre更新到front上,然后向后扫描……注意一行最后一个元素的更新! # 这样迭代n次,最后base[m]的值即LCS的值! def lcsLength(x, y): m = len(x) + 1 n = len(y) + 1 length = min(m, n) # 存放箭头方向 base = [0 for i in range(length)] # 已经全部初始化为 0 了 上↑ 左← 左上↖ for i in range(1, m): # 进入下一行时 front = 0 front = 0 for j in range(1, n): # 数组第一个 元素 下标为 0 front值上移成为下一行的上方值 pre值前移成为下一个的front值 if x[i-1] == y[j-1]: pre = base[j-1] + 1 base[j - 1] = front front = pre elif base[j] >= front: pre = base[j] base[j - 1] = front front = pre else: pre = front base[j - 1] = front front = pre # 因为base最后一个元素在判断中没被更新,所以一行循环结束时,单独把base末尾元素更新 if j == n-1: base[j] = front print(base) return base[length - 1] x = ['A', 'B', 'C', 'B', 'D', 'A', 'B'] y = ['B', 'D', 'C', 'A', 'B', 'A'] count = lcsLength(x, y) print("其最长公共子序列长度为:", count)
转载于:https://my.oschina.net/xiaohuoer1995/blog/1600191