zoukankan      html  css  js  c++  java
  • 最长公共子序列 (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;
    }
  • 相关阅读:
    Libevent库学习笔记
    最大的k个数问题
    MongoDB之整库备份还原单表collection备份还原
    精通MATLAB混合编程
    AutoCAD 2016中文版从入门到精通(第2版)
    MATLAB科学计算范例实战速查宝典
    Android系统应用开发实战详解
    AutoCAD快捷命令速查大全
    TCP IP入门经典(第5版)
    STC8系列单片机开发指南:面向处理器、程序设计和操作系统的分析与应用
  • 原文地址:https://www.cnblogs.com/iloveysm/p/12274529.html
Copyright © 2011-2022 走看看