1. 问题
给定两个序列X,Y,求出X,Y的最长公共子序列
2. 解析
首先要引入一个定理来使得问题能够被简化。
在Zk是Xi和Yj的最长子序列的情况下(其中Xi表示长度为i的X序列)
(1)xi=yj,那么zk=xi=yj
(2)xi!=yj,zk!=xi,那么Zk是Xi-1和Yj的最长子序列
(3)xi!=yj,zk!=yj,那么Zk是Xi和Yj-1的最长公共子序列。
主要使用动态规划的方法来解决这个问题,主要引入两个二维数组来对中间过程进行存储。使用C[I,j]来表示Xi与Yj的最长公共子序列的长度。使用B[I,j]来存储在简化问题时的具体内容。通过引入C[I,j]来得到递推关系
3. 设计
得到最长字串长度
C[0,j] = C[I,0] = 0,1 <= I <= m,1<= j <= n
For I = 1 to m
For j = 1 to n
If(xi == yi)
{
B[I,j] = BOTH //记录删除两个
C[I,j] = C[i-1,j-1]+1
}
Else
{
If(C[I,j-1]>C[i-1,j])
{
C[I,j] = C[I,j-1];
B[I,j] = LEFT//删除Y
}
Else
{
C[I,j] = C[I-1,j];
B[I,j] = RIGHT//删除Y
}
}
求出最长字串
Void find(B,I,j)
{
If I == 0 or j == 0
Return
If B[I,j] = BOTH
输出X[i]
Find(B,i-1,j-1)
Else if B[I,j] = LEFT
Find(B,i-1,j)
Else
Find(B,I,j-1)
}
4. 分析
算法由两部分构成,求出最长公共字符串长度与求出最长字串。前一部分的时间复杂度远大于后一部分,因此忽略后一部分时间复杂度。而在前一部分中,最主要的部分是一个二重循环,因此时间复杂度为O(mn)。