zoukankan      html  css  js  c++  java
  • 最长公共子序列(仅借助数组dp本身在O(m+n)时间内构造最长公共子序列)

    算法课上机作业,想复杂了。。

    给定2个序列X={x1,x2,,xm}Y={y1,y2,,yn},找出XY的最长公共子序列。 改进LCS函数,不使用数组b而仅借助数组c本身在O(m+n)时间内构造最长公共子序列。

    原来的代码:

    void LCSLength(char *x ,char *y,int m,int n, int **c, int **b)
    {
           int i ,j;
           for (i = 1; i <= m; i++) c[i][0] = 0;
           for (i = 1; i <= n; i++) c[0][i] = 0;
           for (i = 1; i <= m; i++)
              for (j = 1; j <= n; j++)
              {
                if (x[i]==y[j])
                {
                     c[i][j]=c[i-1][j-1]+1;
                     b[i][j]=1;
                }
                else if (c[i-1][j]>=c[i][j-1])
                {
                     c[i][j]=c[i-1][j];
                     b[i][j]=2;
                }
                else
                {    c[i][j]=c[i][j-1];
                     b[i][j]=3;
                }
             }
    }
    void LCS(int i ,int j, char *x ,int **b)
    {
          if (i ==0 || j==0) return;
          if (b[i][j]== 1)
          {
               LCS(i-1,j-1,x,b);
               printf("%c",x[i]);
          }
          else if (b[i][j]== 2)
               LCS(i-1,j,x,b);
          else LCS(i,j-1,x,b);
    }

    在打印最后结果的时候,不再使用b[][]数组进行标记。其实也很简单,在打印函数中对b[][]状态判断的时候,再重新看作dp之间的比较即可。

    注意在求LCS时不要用max求,因为如果两个参数相等时并不知道选择了哪一个。代码如下:

    #include<iostream>
    #include<string>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int dp[200][200];
    string s1,s2;
    int len1,len2;
    void print(int i,int j) //打印路径 
    {
        if(i==0||j==0)
        return ;
        if(s1[i-1]==s2[j-1])
        {
            print(i-1,j-1);
            cout<<s1[i-1];
        }
        else
        {
            if(dp[i-1][j]>=dp[i][j-1])
            print(i-1,j);
            else
            print(i,j-1);
        }
    }
    int main()
    {
    
        while(1)
        {
            cout<<"请输入第一个字符串:"<<endl;
            cin>>s1;
            cout<<"请输入第二个字符串:"<<endl;
            cin>>s2;
            len1=s1.length();
            len2=s2.length();
            for(int i=0;i<=len1;i++)
            dp[i][0]=0;
            for(int i=0;i<=len2;i++)
            dp[0][i]=0;
            for(int i=1;i<=len1;i++)
            {
                for(int j=1;j<=len2;j++)
                {
                    if(s1[i-1]==s2[j-1])//子串中第i个和j个相等 
                    dp[i][j]=dp[i-1][j-1]+1;
                    else
                    {
                        //dp[i][j]=max(dp[i-1][j],dp[i][j-1]);此处注意 
                        if(dp[i-1][j]>=dp[i][j-1])
                        dp[i][j]=dp[i-1][j];
                        else
                        dp[i][j]=dp[i][j-1];
                    }
                }
            }
           cout<<"最长公共子序列的长度是: "<<dp[len1][len2]<<endl;
           print(len1,len2);
           cout<<endl;
    
        }
        return 0;
    }
  • 相关阅读:
    《Windows游戏编程技巧大师》就DirectDraw而创建DirectDraw知识笔记
    中国省城市列表(中国的性格+拼音)
    Android NDK的C++11标准支持
    DFGUI-- 标签交换 Tabstrip
    Ubuntu更改hosts档
    如何完成Nexus 9上电后激活过程
    Exception dispatching input event. use XlistView
    音乐TV2015校园招聘A第二大发行量(对中国科学院大学站)
    github basic usage in windows
    HDU 1501 Zipper(DP,DFS)
  • 原文地址:https://www.cnblogs.com/Tach-ac/p/4412993.html
Copyright © 2011-2022 走看看