Java算法之最长公共子序列问题(LCS)实例分析

  

本文实例讲述了Java算法之最长公共子序列问题(LCS)。分享给大家供大家参考,具体如下:

  

:一个给定序列的子序列是在该序列中删去若干元素后得到的序列。确切地说,若给定序列X=1, 2,…, m,则另一序列Z=1, 2,…, k是X的子序列是指存在一个严格递增的下标序列1,2,…,k,使得对于所有j=1, 2,…, k有ij=j。例如,序列Z={B, C, D, B}是序列X={A, B, C, B, D, A, B}的子序列,相应的递增下标序列为{2、3、5、7}。给定两个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。例如,若X={A, B, C, B, D, A, B}和Y={B、D、C、A、B一},则序列{B, C,一个}是X和Y的一个公共子序列,序列{B, C, B,}也是X和Y的一个公共子序列。而且,后者是X和Y的一个最长公共子序列,因为X和Y没有长度大于4的公共子序列。给定两个序列X=1, 2,…, m和Y=1, 2,…, n,要求找出X和Y的一个最长公共子序列。

  

:设X={A, B, C, B, D, A, B}, Y={B、D、C、A、B一}。求X, Y的最长公共子序列最容易想到的方法是穷举法,对X的多有子序列,检查它是否也是Y的子序列,从而确定它是否为X和Y的公共子序列。由集合的性质知,元素为m的集合共有2 ^ m个不同子序列,因此,穷举法需要指数级别的运算时间。进一步分解问题特性,最长公共子序列问题实际上具有最优子结构性质。

  

设序列X=1, 2,……m和Y=1, 2,……n的最长公共子序列为Z=1, 2,……k。则有:

  

(1)若m=n,则k=m=n,且k - 1是m - 1和n - 1的最长公共子序列。
  (2)若m !=n且k !Z=m,则是m - 1和的最长公共子序列。
  (3)若m !=n且k !Z=n,则是和n - 1的最长公共子序列。
  其中,m - 1=1,2……m - 1, n - 1=1, 2……n, k - 1=1,2……k - 1。

  

:用c[我][j]记录序列i和j的最长公共子序列的长度,其中,i=1、2……i, j=1, 2……j。当我=0或j=0时,空序列是i和j的最长公共子序列。此时,c[我][j]=0;当我j> 0,ξ=yj时,c[我][j]=c(张)(j - 1) + 1;当我j> 0,我!=j时,
  [我]c [j]=max {c[我][j - 1], c(张)[j]},由此建立递推关系如下:

  

癑ava算法之最长公共子序列问题(LCS)实例分析"

  

:由以上分析可知,要找出X=1, 2,……m和Y=1, 2,……n的最长公共子序列,可以按一下方式递归进行:当m=n时,找出m - 1和n - 1的最长公共子序列,然后在尾部加上m (=n)即可得X和Y的最长公共子序列。当m !=n时,必须解两个子问题,即找出Xm-1和Y的一个最长公共子序列及X和Yn-1的一个最长公共子序列。这两个公共子序列中较长者为X和Y的最长公共子序列。设数组b[我][j]记录c[我][j]的值由哪一个子问题的解得到的,从b [m] [n]开始,依其值在数b组中搜索,当b[我][j]=1时,表示Xi和Yj的最长公共子序列是由ξ1和Yj-1的最长公共子序列在尾部加习上所得到的子序列。当b[我][j]=2时,表示Xi和Yj的最长公共子序列与ξ1和Yj-1的最长公共子序列相同。当b[我][j]=3时,表示Xi和Yj的最长公共子序列与习近平和Yj-1的最长公共子序列相同。

  

代码如下:

        包LCS;   公开课LCS {   公共静态int [] [] LCSLength (String [] x, String [] y) {   int m=x.length;   int n=y.length;   int [] [] b=new int [x.length] [y.length];   int [] [] c=new int [x.length] [y.length];   for (int i=1;我& lt;m;我+ +){   c[我][0]=0;   }   for (int i=1;我& lt;n;我+ +){   [我]c [0]=0;   }   for (int i=1;我& lt;m;我+ +){   for (int j=1;j & lt;n;j + +) {   如果(x[我]==y [j]) {   [我]c [j]=c(张)(j - 1) + 1;   b[我][j]=1;   }   else if (c(张)[j]祝辞=c[我][j - 1]) {   [我]c [j]=c(张)[j];   b[我][j]=2;   }   其他{   [我][j]=c[我][j - 1];   b[我][j]=3;   }   }   }   返回b;   }   公共静态孔隙LCS (int [] [] b, String [] x, int, int j) {   如果(i==0 | | j==0)返回;   如果(b[我][j]==1) {   LCS (b, x,我- 1 j - 1);   system . out。打印(x[我]+ " ");   }   else if (b[我][j]==2) {   LCS (b, x - 1, j);   }   其他的LCS (b, x, i, j - 1);   }   公共静态void main (String参数[]){   System.out.println(“测试结果:”);   x={String []”、“A”“B”,“C”,“B”,“D”,“A”、“B”};   String [] y={"”、“B”、“D”、“C”,“A”、“B”,“一个"};   int [] [] b=LCSLength (x, y);   System.out.println (“X和y的最长公共子序列是:”);   LCS (b, x, x。长度- 1,y。长度- 1);   }   }      

Java算法之最长公共子序列问题(LCS)实例分析