我可以使用自顶向下的动态编程方法打印LCS吗?

时间:2017-10-30 11:08:30

标签: dynamic-programming

我知道有一种使用自下而上方法的解决方案。但我无法在任何地方使用自上而下的方法找到任何解决方案。这是我用来查找LCS中字符数的代码:

#include <bits/stdc++.h>

using namespace std;

int memo[100][100];


int LCS(string a,string b,int x,int y){
    if(x==a.size() || y==b.size())
    { memo[x][y]=0; 

        return 0;

     }

    if(a[x]==b[y])
    {   


        if(memo[x][y]==-1){
            memo[x][y]=LCS(a,b,x+1,y+1);
        }

        return 1+ memo[x][y];

    }
    else
    {       
        if(memo[x][y]==-1)
            memo[x][y]=max(LCS(a,b,x+1,y),LCS(a,b,x,y+1));

           return memo[x][y];
    }
}

int main(int argc, char const *argv[])
{
    string a,b;
    cin>>a>>b;
    memset(memo,-1,sizeof(memo));
    cout<<LCS(a,b,0,0)<<endl;
    return 0;
}

1 个答案:

答案 0 :(得分:2)

在比较两个字符串时,您需要使用memo来执行此操作。如果它们相等,你会跳到对角线上,如果它们不同,你可以向上看并向左跳跃到主要的那个。

我有一个类似于你的代码。唯一的区别是我从结尾看到字符串的开头:

int lcs(char *x, char *y, int px, int py)
{
    int ans;
    int m1, m2;
    if (memo[px][py] > -1) {
         return memo[px][py];
    }
    if ((px == 0) || (py == 0)) {
        ans = 0;
    } else if (x[px - 1] == y[py - 1]) {
        ans = lcs(x, y, px - 1, py - 1) + 1;
    } else {
        m1 = lcs(x, y, px    , py - 1);
        m2 = lcs(x, y, px - 1, py    );
        //max (m1, m2)
        if (m1 > m2) {
            ans = m1;
        } else {
            ans = m2;
        }
    }
    memo[px][py] = ans;
    return ans;
}

要致电lcs,您可以lcs("marvin", "panic", strlen("marvin"), strlen("panic"))

因此,我的memo(考虑到您的解决方案而被倒置)将生成下表:

+-------------------------+
|         p  a  n  i  c   |
+-------------------------+
|   | -1  0  0  0  0  0   |
| m |  0  0  0  0  0  0   |
| a |  0  0  1  1  1  1   |
| r |  0  0  1  1  1  1   |
| v |  0  0  1  1  1  1   |
| i |  0  0  1 -1  2  2   |
| n | -1 -1 -1  2  2  2   |
+-------------------------+

要恢复子字符串,我们从两个字符串的末尾开始([6,5])并查找相等的字符。如果它们不相等,我们会在向上的位置查看表格的内容。如果这个位置比左边大,我们就往上走,否则我们走到左边。这表示以下代码:

px = strlen("marvin");
py = strlen("panic");
pos = 0;
while ((px != 0) && (py != 0)) {
    if (x[px - 1] == y[py - 1]) {
        res[pos++] = x[px - 1];
        px--;
        py--;
    } else if (memo[px - 1][py] > memo[px][py -1]) {
        px--;
    } else {
        py--;
    }
}
res[pos] = '\0';
printf("%s\n", strrev(res));

这段代码将从最后开始,然后向左移动,直至找到字符n(位置F)。

+-------------------------+
|         p  a  n  i  c   |
+-------------------------+
|   | -1  0  0  0  0  0   |
| m |  0  0  0  0  0  0   |
| a |  0  0  1  1  1  1   |
| r |  0  0  1  1  1  1   |
| v |  0  0  1  1  1  1   |
| i |  0  0  P -1  2  2   |
| n | -1 -1 -1  F  -  -   |
+-------------------------+

当找到char n时,算法位置会跳到左上角(位置P)。在接下来的步骤中,算法会一直运行,直到与char a匹配。

+-------------------------+
|         p  a  n  i  c   |
+-------------------------+
|   | -1  0  0  0  0  0   |
| m |  0  P  0  0  0  0   |
| a |  0  0  F  1  1  1   |
| r |  0  0  |  1  1  1   |
| v |  0  0  |  1  1  1   |
| i |  0  0  | -1  2  2   |
| n | -1 -1 -1  \  -  -   |
+-------------------------+

最后一步将继续,直到px的位置达到零并且算法停止。

+-------------------------+
|         p  a  n  i  c   |
+-------------------------+
|   | -1  0  0  0  0  0   |
| m |  -  -  0  0  0  0   |
| a |  0  0  \  1  1  1   |
| r |  0  0  |  1  1  1   |
| v |  0  0  |  1  1  1   |
| i |  0  0  | -1  2  2   |
| n | -1 -1 -1  \  -  -   |
+-------------------------+

Obs:结果为na,需要还原(an)。