LCS最长公共子序列的延伸情况(可连续的子序列)

     看过《算法导论》的人应该知道,动态规划中一个非常经典的例子就是LCS(Longest Common Length)最长公共子序列问题。下面我们来回顾一下LCS的概念。

    假设有两个字符串,X=<A, B, C, B, D, A, B>,Y=<B, D, C, A, B, A>,那么它们的最长公共子序列为<B, C, B, A>,它的特点在于每个字符可以不连续。LCS问题在实际中也有非常多的应用,比如说用于论文查重等。

    都说表达一个动态规划算法的精髓在于状态转移方程,那么我们就顺便回忆一下LCS的状态转移方程吧。如果用c[i, j]来表示序列Xi和Yi的LCS的长度,那么有状态转移方程:

 

    下面进入本文的重点。如果将LCS的条件加严,要求子序列中的字符必须是连续的。那么应该如何求解这个最长公共连续子序列呢?

    为了便于书写,后文中再提到“最长公共连续子序列”,我都一律用STRICT-LCS代替。

    为了便于理解,还是用之前的两个字符串来举例说明什么是STRICT-LCS。X=<A, B, C, B, D, A, B>,Y=<B, D, C, A, B, A>。那么它们的最长公共连续子序列为<B, D>。

    我们仍然用Dynamic Programming求解。只不过在原来的基础上需要改变。首先,我们定义c[i, j]跟原来的意义略有不同。这里c[i, j]指的是最后一个元素为Xi(=Yj)的STRICT-LCS的长度,比如X=<A, B, C>,Y=<A, B, D>那么c[3, 3]=0,不管前面如何,如果Xi和Yj不相等,就得将c[i, j]清零,作为新的开始。

    LCS中,c[i, j]的值随着i、j值增大而渐渐增大,有累计效应;但是STRICT-LCS中,c[i, j]的值随时可能在某个时刻被清零。

    说了这么多,把状态转移方程写出来吧:

 

    伪代码的话,也比较简单。

 1 STRICT-LCS-LENGTH(X, Y)
 2 m = length[X]
 3 m = length[Y]
 4 for i = 1 to m
 5     do c[i, 0] = 0
 6 for j = 0 to n
 7     do c[0, j] = 0
 8 for i = 1 to m
 9     do for j = 1 to n
10         do if Xi=Yj
11             then c[i, j] = c[i-1, j-1]+1
12             else c[i, j] = 0
13 return c

  

    下面做一个显示推导过程的图。 

   

    从上图中可以找到值最大的格子2,故可知X和Y的最长公共连续子序列为BD,和AB,两个子序列的长度都为2.

e

posted @ 2012-10-30 21:16  ErinFlyingFish  阅读(6112)  评论(1编辑  收藏  举报