动态规划(四)最长公共子序列问题

       除了背包问题和走金字塔问题,最长公共子序列也是常见动态规划例子,本篇文章简单分析该问题。

       最长公共子序列问题形式如下:有两个字符串,求出最长公共子序列的长度。示例如:

           字符串A:  a  s d  h  e  j  f

           字符串B:  a  r  s  g  k  l  g  d

       则字符串A和B的最长公共子序列为“asd”,最大公共子序列长度为3。最长公共子序列与最长公共子串不同的是:最长公共子序列是两个字符串中抽取出来的出现顺序相同、但不必连续的子串,最长公共子串是两个字符串中抽取出来的出现顺序相同、也要连续的子串。

       与0-1问题的解法类似,此问题分析步骤如下:

           1、用一个多维数组dp的形式来模拟计算过程,数组的初始值可以用0来填充。

           2、定义状态。如dp[ i ][  j ],定义为字符串A[0...i]和字符串B[0...j]的最长公共子序列长度。关于dp[ i ][ j ] 的变化过程,可以分为两类:

                 1>当A[ i ]和B[ j ]相等时,则两个字符串需要公共减去共有序列,然后最长公共子序列数量+1,即dp[ i ][ j ] =   dp[ i-1 ][ j-1 ] +1。

                 2>当A[ i ]和B[ j ]不相等时,就需要将A或B的字符串减去1个元素,然后取两者的最大值,即dp[ i ][  j ] = max(dp[ i-1 ][ j ],dp[ i ][ j-1 ])。

              当最后填满数组dp时,dp[ A.length() ][ B.length() ]即为所求的最长公共子序列长度。

       Java代码如下: 

            String str1 = "asdhejf";
            String str2 = "arsgklgd";
            //构建动态规划表
            int[ ][ ] dp = new int[str1.length() + 1][str2.length() + 1];
            //赋予动态规划表初始值
            for (int i = 0; i <= str1.length(); i++) {
                 for (int j = 0; j <= str2.length(); j++) {
                      dp[ i ][ j ] = 0;
                  }
             }
        
             for (int i = 1; i <= str1.length(); i++) {
                 for (int j = 1; j <= str2.length(); j++) {
                    if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
                         //两个字符串中要比较的元素相等
                         dp[ i ][ j ] = dp[i - 1][j - 1] + 1;
                     } else {
                         //两个字符串中要比较的元素不相等,分别在两个字符串中减去一元素,取较大值
                         dp[ i ][ j ] = Math.max(dp[i - 1][j],dp[i][j - 1]);
                    }
                }
            }

原创文章 9 获赞 0 访问量 601

猜你喜欢

转载自blog.csdn.net/m0_37741420/article/details/105257341