zoukankan      html  css  js  c++  java
  • 51 nod 1006 最长公共子序列Lcs

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1006

    参考博客 :http://blog.csdn.net/yysdsyl/article/details/4226630

    recursive formula 

    引进一个二维数组c[][],用c[i][j]记录X[i]与Y[j] 的LCS 的长度,b[i][j]记录c[i][j]是通过哪一个子问题的值求得的,以决定搜索的方向。
    我们是自底向上进行递推计算,那么在计算c[i,j]之前,c[i-1][j-1],c[i-1][j]与c[i][j-1]均已计算出来。此时我们根据X[i] = Y[j]还是X[i] != Y[j],就可以计算出c[i][j]。

    计算 LCS 复杂度  O(n*m).由于每次调用至少向上或向左(或向上向左同时)移动一步,故最多调用(m + n)次就会遇到i = 0或j = 0的情况,此时开始返回。返回时与递归调用时方向相反,步数相同,故打印输出算法时间复杂度为Θ(m + n)。

    打印序列,非递归。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <set>
     5 #include <queue>
     6 #include <algorithm>
     7 #define MAXN 1111
     8 #define MAXM 222222
     9 #define INF 1000000000
    10 using namespace std;
    11 
    12 char s[MAXN],t[MAXN],res[MAXN];
    13 int dp[MAXN][MAXN],flag[MAXN][MAXN];
    14 
    15 void LCS(int n,int m)
    16 {
    17     memset(dp,0,sizeof(dp));
    18     memset(flag,0,sizeof(flag));
    19     for(int i=1;i<=n;i++)
    20         for(int j=1;j<=m;j++)
    21         {
    22             if(s[i-1]==t[j-1])
    23             {
    24                 dp[i][j]=dp[i-1][j-1]+1;
    25                 flag[i][j]=1;
    26             }
    27             else if(dp[i][j-1]>dp[i-1][j])
    28             {
    29                 dp[i][j]=dp[i][j-1];
    30                 flag[i][j]=2;
    31             }
    32             else
    33             {
    34                 dp[i][j]=dp[i-1][j];
    35                 flag[i][j]=3;
    36             }
    37         }
    38     //printf("%d
    ",dp[n][m]);
    39 }
    40 
    41 void getLCS(int n,int m)
    42 {
    43     int k=0;
    44     while(n>0&&m>0)
    45     {
    46         if(flag[n][m]==1)
    47         {
    48             res[k++]=s[n-1];
    49             n--;
    50             m--;
    51         }
    52         else if(flag[n][m]==2) m--;
    53         else if(flag[n][m]==3) n--;
    54     }
    55     for(int i=k-1;i>=0;i--)
    56     {
    57         printf("%c",res[i]);
    58     }
    59     printf("
    ");
    60 }
    61 
    62 int main()
    63 {
    64     //freopen("a.txt","r",stdin);
    65     scanf("%s %s",s,t);
    66     //printf("%s %s
    ",s,t);
    67     int l1=strlen(s),l2=strlen(t);
    68     LCS(l1,l2);
    69     /*for(int i=0;i<=l1;i++)
    70     {
    71         for(int j=0;j<=l2;j++)
    72             printf("%d ",flag[i][j]);
    73         printf("
    ");
    74     }
    75     printf("
    ");*/
    76     getLCS(l1,l2);
    77     return 0;
    78 }
    View Code

    递归

     1 #include<cstdio>
     2 #include<cstring>
     3 const int maxn=1111;
     4 int dp[maxn][maxn],flag[maxn][maxn];
     5 int n,m;
     6 char s[maxn],t[maxn];
     7 
     8 void LCS(int n,int m)
     9 {
    10     memset(dp,0,sizeof(dp));
    11     memset(flag,0,sizeof(flag));
    12     for(int i=0;i<n;i++)
    13         for(int j=0;j<m;j++)
    14         {
    15             if(s[i]==t[j])
    16             {
    17                 dp[i+1][j+1]=dp[i][j]+1;
    18                 flag[i+1][j+1]=1;
    19             }
    20             else if(dp[i+1][j]>dp[i][j+1])
    21             {
    22                 dp[i+1][j+1]=dp[i+1][j];
    23                 flag[i+1][j+1]=2;
    24             }
    25             else
    26             {
    27                 dp[i+1][j+1]=dp[i][j+1];
    28                 flag[i+1][j+1]=3;
    29             }
    30         }
    31    // printf("%d
    ",dp[n][m]);
    32 }
    33 
    34 void printLCS(int n,int m)
    35 {
    36     if(n==0||m==0) return;
    37 
    38     if(flag[n][m]==1)
    39     {
    40         printLCS(n-1,m-1);
    41         printf("%c",s[n-1]);
    42     }
    43     else if(flag[n][m]==2) printLCS(n,m-1);
    44     else printLCS(n-1,m);
    45 }
    46 int main()
    47 {
    48     //freopen("a.txt","r",stdin);
    49     scanf("%s %s",s,t);
    50     int l1=strlen(s),l2=strlen(t);
    51     LCS(l1,l2);
    52     printLCS(l1,l2);
    53     return 0;
    54 }
    View Code

    下面这种是比较简洁的。去掉了标记数组。

     1 #include<string>
     2 #include<iostream>
     3 using namespace std;
     4 const int maxn = 1111;
     5 
     6 int dp[maxn][maxn]={0};
     7 string a,b;
     8 
     9 void LCS(int n,int m)
    10 {
    11     for(int i=1;i<=n;i++)
    12         for(int j=1;j<=m;j++)
    13         if(a[i-1]==b[j-1]) dp[i][j]=dp[i-1][j-1]+1;
    14         else dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
    15 }
    16 
    17 int main()
    18 {
    19     cin>>a>>b;
    20     int l1=a.size(),l2=b.size();
    21     LCS(l1,l2);
    22     int len=dp[l1][l2];
    23     string ans;
    24     int i=l1,j=l2;
    25     while(dp[i][j])
    26     {
    27         if(dp[i][j]==dp[i-1][j]) i--;
    28         else if(dp[i][j]==dp[i][j-1]) j--;
    29         else ans.push_back(a[i-1]),i--,j--;
    30     }
    31     for(int i=len-1;i>=0;i--)
    32         cout<<ans[i];
    33     return 0;
    34 }
    View Code
  • 相关阅读:
    Python字符串
    ListCtrl控件
    leetcode1004
    leetcode1003
    leetcode1002
    leetcode153
    leetcode540
    leetcode435
    leetcode999
    leetcode997
  • 原文地址:https://www.cnblogs.com/nowandforever/p/4429099.html
Copyright © 2011-2022 走看看