动态规划最长公共子序列(LCS)问题(Java 实现)
动态规划最长公共子序列(LCS)问题(Java 实现)
首先,明白一个公共子序列和公共子串的区别
公共子序列: 可以不连续
公共子串: 必须连续
问题分析
求最长公共子序列,先明白两个概念
子序列
一个给定序列中删去若干元素后得到的序列
公共子序列
给定两个序列 X,Y,当另一序列 Z 既是 X 的子序列,又是 Y 的子序列时,就称 Z 为 X、Y 的公共子序列
明白上述两个概念后,我们就可以开始搜索最长公共子序列
这个问题可以使用暴力方法解决,但是由于要全部搜索一遍,时间复杂度为 O(n2<sup>m</sup>),所以我们不采用
我们可以使用动态规划算法,自底向上进行搜索,这样,在计算后面的时候,前面的数据我们已经对其进行保存,直接进行计算即可,时间复杂度很大程度降低。
既然决定使用动态规划算法,首先引入一个二位数组 c[][], 记录 x[i] 与 y[j] 的 LCS 的长度,b[i][j] 记录 c[i][j] 的通过哪一个子问题的值求得的,以决定搜索方向。
抽取状态转移方程(X=x<sub>1</sub>x<sub>2</sub>...x<sub>m</sub>、Y=y<sub>1</sub>y<sub>2</sub>...y<sub>n</sub>为两个序列,Z=z<sub>1</sub>z<sub>2</sub>...z<sub>k</sub>为公共子序列)
对于 x[i] 和 y[j], 若 i = 0 or j = 0,显然,c[i][j] = 0
若 i = j,我们可以使用上一步计算的值直接进行计算,即 c[i][j] = c[i-1][j-1] + 1
若 i ≠ j,有两种情况
Z<sub>k</sub> ≠ X<sub>m</sub>,那么 Z 一定是 X<sub>m-1</sub>, Y 的一个公共子序列,
Z<sub>k</sub> ≠ Y<sub>n</sub>,那么 Z 一定是 X, Y<sub>n-1</sub> 的一个公共子序列
这样,第三种情况我们就可以表示成: c[i][j] = max{c[i-1][j], c[i][j-1]}
那么,我们就可以写出其状态转移方程
Java 代码实现
版权声明: 本文为 InfoQ 作者【若尘】的原创文章。
原文链接:【http://xie.infoq.cn/article/b9e0f71e9d08fe7f41a7dc8b6】。文章转载请联系作者。
评论