最长公共子序列是来自于leetcode的一道编程题。典型的动态规划思路,动态规划相比于递归算法的重要区别在于:递归算法是从完整的大规模问题逐步划分为小规模的问题,是自顶向下的分而治之策略。而动态规划则是从小规模问题着手,自底向上的思路。动态规划也可以理解为是迭代的思路,当前状态的数值取决于前面时刻的状态,这种情况下将使用动态规划会比代码看上去很简单的递归算法节省很多重复的递归实例计算。
子序列指的是:在字符串中取出某些字符构成新字符串,在原字符串和新字符串中的字符相对位置不变。
动态规划的具体思路如下:
首先考虑两个长的完整字符串advantage和didactical,记作A和B,它们的公共子序列怎么求解呢?考虑两个长字符串的最后一个字符A[-1]和B[-1],试想:如果最后一个字符相等A[-1]=B[-1],则最长子序列长度为字符串A[:-1]和B[:-1]的最长子序列长度+1,这里对于列表的索引采用python的习惯,也就是:左闭右开区间,右边界的端点值取不到。如果A[-1]!=B[-1],也就是例子中的情况,则最长子序列的长度等于 max(A[:-1]和B的最长子序列,A和B[:-1]的最长子序列)。
解决方案是填充一个二维表格,先填充第1行所有列,再填充第二行所有列的顺序,这样每当要求表格中当前数值时,只需判断当前位置上的两个字符是否相等,如果相等,则等于对角线上上一个位置的值加1,否则等于其上方和其左方的最大值,对于表格的填充顺序必须满足这样的方案可行。
# -*- coding:utf-8 -*- class LCS: def findLCS(self, A, n, B, m): # write code here table=[[0 for i in range(m+1)] for j in range(n+1)] print(len(table),len(table[0])) for p in range(1,n+1): for q in range(1,m+1): if A[p-1]==B[q-1]: table[p][q]=table[p-1][q-1]+1 else: print(p,q) print(table[p-1]) print(table[p]) table[p][q]=max(table[p-1][q],table[p][q-1]) return table[n][m] if __name__=='__main__': output=LCS().findLCS("1A2C3D4B56",10,"B1D23CA45B6A",12) print(output)