Java基于动态规划法实现求最长公共子序列及最长公共子字符串示例

  

本文实例讲述了Java基于动态规划法实现求最长公共子序列及最长公共子字符串。分享给大家供大家参考,具体如下:

  

<强>动态规划法

  

经常会遇到复杂问题不能简单地分解成几个子问题,而会分解出一系列的子问题。简单地采用把大问题分解成子问题,并综合子问题的解导出大问题的解的方法,问题求解耗时会按问题规模呈幂级数增加。

  

为了节约重复求相同子问题的时间,引入一个数组,不管它们是否对最终解有用,把所有子问题的解存于该数组中,这就是动态规划法所采用的基本方法。

  

<强>

  

问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列X=皒0, x1,…, xm-1序列Y=皔0, y1,…, yk-1”是X的子序列,存在X的一个严格递增下标序列& lt;钱数,i1,…, ik-1>使得对所有的j=0, 1,…, k - 1,有xij=yj。例如,X=癆BCBDAB”, Y=癇CDB”是X的一个子序列。

  

考虑最长公共子序列问题如何分解成子问题,设一个=癮0, a1,…, am-1”, B=癰0, b1,…, bm-1”,并Z=皕0 z1,…, zk-1”为它们的最长公共子序列。不难证明有以下性质:

  

(1)如果am-1=bn-1则zk-1=am-1=bn-1,且“z0 z1,…, zk-2”是“a0, a1,…, am-2”和“b0, b1,…, bn-2”的一个最长公共子序列;

  

(2)如果am-1 !=bn-1,则若zk-1 !=am-1蕴涵”z0 z1,…, zk-1”是“a0, a1,…, am-2”和“b0, b1,…, bn-1”的一个最长公共子序列;

  

(3)如果am-1 !=bn-1,则若zk-1 !=bn-1蕴涵”z0 z1,…, zk-1”是“a0, a1,…, am-1”和“b0, b1,…, bn-2”的一个最长公共子序列。

  

这样,在找A和B的公共子序列时,如有am-1=bn-1则进一步解决一个子问题,找“a0, a1,…, am-2”和“b0, b1,…, bm-2”的一个最长公共子序列;如果am-1 !=bn-1,则要解决两个子问题,找出“a0, a1,…, am-2”和“b0, b1,…, bn-1”的一个最长公共子序列和找出“a0, a1,…, am-1”和“b0, b1,…, bn-2”的一个最长公共子序列,再取两者中较长者作为A和B的最长公共子序列。

  

<强>求解:

  

引进一个二维数组c[][],用c[我][j]记录X[我]与[j]的LCS的长度,b[我][j]记录c[我][j]是通过哪一个子问题的值求得的,以决定搜索的方向。
  我们是自底向上进行递推计算,那么在计算c (i, j)之前,c(张)(j - 1), c(张)[j] c[我]与[j - 1]均已计算出来。此时我们根据X[我]=[j]还是X[我]!=Y [j],就可以计算出c[我][j] .

  

问题的递归式写成:

  

癑ava基于动态规划法实现求最长公共子序列及最长公共子字符串示例"

  

回溯输出最长公共子序列过程:

  

癑ava基于动态规划法实现求最长公共子序列及最长公共子字符串示例"

  

<强>算法分析:

  

由于每次调用至少向上或向左(或向上向左同时)移动一步,故最多调用(m * n)次就会遇到i=0或j=0的情况,此时开始返回。返回时与递归调用时方向相反,步数相同,故算法时间复杂度为Θ(m * n)。

  

<强> Java代码实现:

        公开课LCSProblem   {   公共静态void main (String [] args)   {//保留空字符串是为了getLength()方法的完整性也可以不保留//但是在getLength()方法里面必须额外的初始化c[][]第一个行第一列   x={String []”、“A”“B”,“C”,“B”,“D”,“A”、“B”};   String [] y={"”、“B”、“D”、“C”,“A”、“B”,“一个"};   int [] [] b=getLength (x, y);   显示器(b, x, x。长度是1,y.length-1);   }/* *   * @param x   * @param y   * @return返回一个记录决定搜索的方向的数组   */公共静态int [] [] getLength (String [] x, String [] y)   {   int [] [] b=new int [x.length] [y.length];   int [] [] c=new int [x.length] [y.length];   for (int i=1;iJava基于动态规划法实现求最长公共子序列及最长公共子字符串示例