zoukankan      html  css  js  c++  java
  • LCS

    思路:

      明显的可以想到,状态转移方程为:

      当x[i] == y[j]时,dp[i][j] = dp[i-1][j-1]+1

      当x[i] != y[j]时,dp[i][j] = max(dp[i-1][j], dp[i][j-1])

      这种方法可以结合下面的决策矩阵和代码加深理解(参考自https://blog.csdn.net/linraise/article/details/9104975

      

     1 #include<iostream>
     2 using namespace std;
     3 #define M 7
     4 #define N 6
     5 int b[M + 1][N + 1] = {0}; //存方向
     6 int c[M + 1][N + 1] = {0}; //存值
     7 
     8 void Lcs_Length(char *X, char *Y)
     9 {
    10     int i, j;
    11     for(i = 1; i <= M; i++)
    12         c[i][0] = 0;
    13     for(j = 0; j <= N; j++)
    14         c[0][j] = 0;
    15     for(i = 1; i <= M; i++)
    16     {
    17         for(j = 1; j <= N; j++)
    18         {
    19             if(X[i] == Y[j]) //比较两个字串对应位,如果相等,则=对角+1
    20             {
    21                 c[i][j] = c[i - 1][j - 1] + 1;
    22                 b[i][j] = 1; //1代表↖ 
    23             }
    24             else if(c[i - 1][j] >= c[i][j - 1]) //如果上面值>=下面值
    25             {
    26                 c[i][j] = c[i - 1][j]; //c[i][j]=大值
    27                 b[i][j] = 2; //2代表↑
    28             }
    29             else
    30             {
    31                 c[i][j] = c[i][j - 1]; //赋的总是大值,箭头总是指向大值
    32                 b[i][j] = 3; //3代表←
    33             }
    34         }
    35     }
    36 }
    37 void Print_Lcs(char *X, int i, int j)
    38 {
    39     if(i == 0 || j == 0)
    40         return ;
    41     if(b[i][j] == 1)
    42     {
    43         Print_Lcs(X, i - 1, j - 1);
    44         cout << X[i] << ' '; //只需输出↖对应的值
    45     }
    46     else if(b[i][j] == 2)
    47         Print_Lcs(X, i - 1, j);
    48     else Print_Lcs(X, i, j - 1);
    49 }
    50 int main()
    51 {
    52     char  X[M + 1] = {'0', 'A', 'B', 'C', 'B', 'D', 'A', 'B'};
    53     char  Y[N + 1] = {'0', 'B', 'D', 'C', 'A', 'B', 'A'};
    54     Lcs_Length(X, Y);
    55     Print_Lcs(X, M, N);
    56     cout << endl;
    57     for(int i = 0; i <= M; i++)
    58     {
    59         for(int j = 0; j <= N; j++)
    60         {
    61             cout << c[i][j] << ' ';
    62         }
    63         cout << endl;
    64     }
    65     cout << endl;
    66     for(int i = 0; i <= M; i++)
    67     {
    68         for(int j = 0; j <= N; j++)
    69         {
    70             switch(b[i][j])
    71             {
    72             case 0:
    73             {
    74                 cout << b[i][j] << "  ";
    75                 break;
    76             }
    77             case 1:
    78             {
    79                 cout << '\' << ' ' << ' ';
    80                 break;
    81             }
    82             case 2:
    83             {
    84                 cout << '|' << ' ' << ' ';
    85                 break;
    86             }
    87             case 3:
    88             {
    89                 cout << '-' << ' ' << ' ';
    90                 break;
    91             }
    92             }
    93         }
    94         cout << endl;
    95     }
    96     return 0;
    97 }

     

    进一步分析:

      这种动态规划做法,用空间换取时间,对比暴力法,时间复杂度由O(m2n2)降低到了O(n2),那么有没有什么方法能进一步优化空间复杂度呢?答案是肯定的。分析上面的决策矩阵,发现每一行的值都是由上一行决定的,所以前面行的值是可以舍弃,不必保存的,这就可以使用滚动数组进行空间优化。

    for(i = 1; i <= m; i++)
    {
        for(j = 1; j <= n; j++)
        {
            if(x[i] == y[j])
                dp[i % 2][j] = dp[(i - 1) % 2][j - 1] + 1;
            else if(dp[(i - 1) % 2][j] >= dp[i % 2][j - 1])
                dp[i % 2][j] = dp[(i - 1) % 2][j];
            else
                dp[i % 2][j] = dp[i % 2][j - 1];
        }
    }

       那么O(n2)的时间复杂度能继续优化吗?答案也是肯定的。做法是将LCS问题转换成O(nlogn)的LIS问题来求解,后续补充~

     reference:

    https://blog.csdn.net/linraise/article/details/9104975

  • 相关阅读:
    Objective-C Loops
    HDU 4757 Tree(可持久化Trie+Tarjan离线LCA)
    Codeforces Round #367 (Div. 2) D. Vasiliy's Multiset(可持久化Trie)
    HDU 5416 CRB and Tree(前缀思想+DFS)
    HDU 3695 Computer Virus on Planet Pandora(AC自动机模版题)
    HDU 2222 Keywords Search(AC自动机模版题)
    POJ 2697 A Board Game(Trie判重+BFS)
    HDU 4287 Intelligent IME(字典树数组版)
    HDU 1160 FatMouse's Speed(要记录路径的二维LIS)
    HDU 1565&1569 方格取数系列(状压DP或者最大流)
  • 原文地址:https://www.cnblogs.com/friend-A/p/10298157.html
Copyright © 2011-2022 走看看