本文实例讲述了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]},由此建立递推关系如下:
:由以上分析可知,要找出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)实例分析