1 什么是公共子序列
给定序列X,长度为m,序列Y,长度为n,存在两个严格递增的下表序列
i1,i2,...,ik 和 j1,j2,...,jk 使
X[i1] = Y[j1], X[i2] = Y[j2], ... X[ik] = Y[jk]
则序列<X[i1], X[i2], ..., X[ik]> 或者 Y[j1], Y[j2], ..., Y[jk]是X和Y的一个公共子序列
LCS问题就是找出最长的公共子序列
2 解法
两个序列:
X[1],X[2],...X[m-1], X[m]
Y[1],Y[2],...Y[n-1], Y[n]
求这两个序列的LCS时,可以转化为求子问题。
如果X[m] = Y[n], 则必须找出Xm-1和Yn-1的一个LCS, 然后将
X[m] = Y[n] 添加到这个LCS上,就求出了Xm和Yn的LCS。
如果X[m] != Y[n], 就必须解决两个子问题, 找出Xm-1和Yn的一个LCS,
以及找出Xm和Yn-1的一个LCS,这两个LCS中,较长的就是Xm和Yn的一个LCS
3 除了求长度外,如何求构成LCS的元素
对于序列
X[1],X[2],...X[m-1], X[m]
Y[1],Y[2],...Y[n-1], Y[n]
从后往前打印LCS的元素
如果X[m] = Y[n],则 X[m]或者Y[n]是LCS的一个元素,打印出来
如果X[m] != Y[n],求出Xm-1和Yn的LCS,求出Xm和Yn-1的LCS,
则下一个元素在长度更长的那个LCS中。
使用一个数组b[m][n]
b[m][n] == 0 表示X[m] = Y[n]是LCS的一个元素,下一个元素在Xm-1和Yn-1的LCS中
b[m][n] == 1表示下一个元素在Xm和Yn-1的LCS中
b[m][n] == -1表示下一个元素在Xm-1和Yn的LCS中
b[m][n]数组在求LCS的过程中顺带求出来,然后使用递归调用
print_lcs(m,n)表示打印出序列Xm和Yn的LCS
print_lcs(m,n) {
if (b[m][n] == 0) {
print_lcs(m-1, n-1);
print X[i];
} else if (b[m][n] == 1) {
print_lcs(m, n-1);
} else {
print_lcs(m-1, n);
}
}