子序列的概念
一个序列A中任意删除若干项,剩余的序列叫做A的一个子序列。
也可以认为是从序列A按原顺序保留任意若干项得到的序列。
子序列不是子集,它和原始序列的元素顺序是相关的。
公共子序列的概念
顾名思义,如果序列C既是序列A的子序列,同时也是序列B的子序列,则称它为序列A和序列B的公共子序列。
最长公共子序列
A和B的公共子序列中长度最长的(包含元素最多的)叫做A和B的公共子序列。
子序列、公共子序列以及最长公共子序列都不唯一,但显然最长公共子序列的长度是一定的。
所以,最长公共子序列问题并不是求那个序列,而是求最长的那个长度。
动态规划
定义LCS(x, y)表示x和y的最长公共子序列的长度
下面求A和B的最长公共子序列长度
A[x]和B[y]分别是两个序列的最后一项
首先,考虑子序列最后一项
A[x] == B[y]:
那么它们一定是最长公共子序列的最后一项,可以反证
A[x] != B[y]:
又分为两种情况:从A中去掉A[x],从B中去掉B[y]
这两种继续回到上面递归求解,最后取其中较大的一个的结果
递推公式如下:
按照公式可以写出递归解法:
下面是伪代码
也有非递归解法:
如何构造一个LCS
构造表格
第一步,将序列和下标画成表格
初始化表格
然后就是一行行地填表
填表规则:
如果横竖相等,就取左上角加一
如果横竖不等,就取左边和上边的最大值
构造LCS
构造表格时从第一个往后
构造LCS时要从最后一个向前
横竖相等就减一,向左上角走
横竖不等就取左面和上面较大的那一个
如果横竖不等,且上面和左面一样大,就随便选一个
走到0就结束了,经历的路径就是所求的最长公共子序列
因为最长公共子序列不是唯一的嘛
参考:
https://blog.csdn.net/hrn1216/article/details/51534607
https://blog.csdn.net/so_geili/article/details/53737001
https://blog.csdn.net/lz161530245/article/details/76943991