• 最长公共子序列 (LCS)


    继上次讲完求LCS长度后,来更新一篇具体求LCS的求法。

    in:

    abcicba
    abdkscab
    out:
    abca

    我们已经知道lcs中的状态转移方程为:

    for(int i=0;i<=a;i++)
            {
                for(int j=0;j<=b;j++)
                {
                    if(i==0||j==0)
                    {
                        dp[i][j]=0;
                        continue;
                    }
                    if(s1[i-1]==s2[j-1])
                        dp[i][j]=dp[i-1][j-1]+1;
                    else
                        dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
                }
            }

    得出,在进行dp时,dp[i][j]的状态由三种可能的状态转移过来,第一种状态表示第一个序列的前i-1个字符与第二个序列前j-1个字符的公共子序列加上最后一个字符的录入状态,如果最后的一个字符相等则录入状态为1;第二种状态表示不录入第二个序列的第j个字符时的最长公共子序列;第三种状态表示不录入第一个序列的第i个字符时的最长公共子序列。

    那么有:

    while(i!=0 && j!=0)
    
        {
    
            if(a[i-1] == b[j-1])//对应第一种情况
    
            {
    
                c[z++] = a[--i];//将a[i-1]录入c中
    
                j--;
    
            }
    
            else if(dp[i-1][j] < dp[i][j-1])//第二种
    
                j--;
    
            else if(dp[i][j-1] <= dp[i-1][j])//第三种
    
                i--;
    
        }

    加上完整的路径打印为

    #include<bits/stdc++.h>
    using namespace std;
    char a[1001], b[1001];
    int dp[1001][1001], len1, len2;
    void lcs(int i, int j)
    {
        for(i=1; i<=len1; i++)
        {
            for(j=1; j<=len2; j++)
            {
                if(a[i-1] == b[j-1])
                    dp[i][j] = dp[i-1][j-1] + 1;
                else if(dp[i-1][j] > dp[i][j-1])
                    dp[i][j] = dp[i-1][j];
                else
                    dp[i][j] = dp[i][j-1];
            }
        }
    }
    void getlcs()
    {
        int i, j, z = 0;
        char c[1001];
        memset(c, 0, sizeof(c));
        i = len1, j = len2;
        while(i!=0 && j!=0)
        {
            if(a[i-1] == b[j-1])
            {
                c[z++] = a[--i];
                j--;
            }
            else if(dp[i-1][j] < dp[i][j-1])
                j--;
            else if(dp[i][j-1] <= dp[i-1][j])
                i--;
        }
        for(i=z-1; i>=0; i--)
            printf("%c", c[i]);
        putchar('
    ');
    }
    int main()
    {
        while(~scanf(" %s", a))
        {
            scanf(" %s", b);
            memset(dp, 0, sizeof(dp));
            len1 = strlen(a);
            len2 = strlen(b);
            lcs(len1, len2);
            getlcs();
        }
        return 0;
    }
  • 相关阅读:
    JS基础(一)异常错误
    实验四 主存空间的分配和回收
    实验三、进程调度模拟程序实验
    学习进度条
    软件工程学期总结
    实验四、主存空间的分配和回收
    诚信与道德
    【操作系统】实验三、进程调度模拟程序实验
    软件工程---在此基础上,进行软件的改进
    【操作系统】实验二 作业调度模拟程序
  • 原文地址:https://www.cnblogs.com/iloveysm/p/12274529.html
Copyright © 2020-2023  润新知