zoukankan      html  css  js  c++  java
  • 最长公共上升子序列(LCIS)

      最长公共上升子序列慕名而知是两个字符串a,b的最长公共递增序列,不一定非得是连续的。刚开始看到的时候想的是先用求最长公共子序列,然后再从其中找到最长递增子序列,可是仔细想一想觉得这样有点不妥,然后从网上看了一些大神的理解,觉得恍然大悟。

      定义dp[i][j]表示字符串a前i个和字符串b的前j个且以b[j]结尾构成的最长公共上升子序列的长度,定义一个max用来保存最大的长度。用两个循环,外层循环控制字符串a,内层循环控制字符串b。如果a[i]不等于b[j],则dp[i][j]=dp[i-1][j];如果a[i]大于b[j]而且max<dp[i-1][j],则max=dp[i-1][j];如果a[i]等于b[j],则dp[i][j]=max+1。最后的答案在dp[n][1~m]中最大的。(注意,这种情况是字符串都是从下标为1开始存的)

      下面是例题:  杭电1423

    Greatest Common Increasing Subsequence

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 3482    Accepted Submission(s): 1098


    Problem Description
    This is a problem from ZOJ 2432.To make it easyer,you just need output the length of the subsequence.
     
    Input
    Each sequence is described with M - its length (1 <= M <= 500) and M integer numbers Ai (-2^31 <= Ai < 2^31) - the sequence itself.
     
    Output
    output print L - the length of the greatest common increasing subsequence of both sequences.
     
    Sample Input
    1
    5
    1 4 2 5 -12
    4
    -12 1 2 4
     
    Sample Output
    2
     
    代码如下:
     1 #include <iostream>
     2 using namespace std;
     3 int t,n,m;
     4 int a[503],b[503];
     5 int dp[503][503];
     6 
     7 int LCIS()
     8 {
     9     int i,j;
    10     int max;
    11     for(i=1;i<=n;i++)
    12     {
    13         max = 0;
    14         for(j=1;j<=m;j++)
    15         {
    16             dp[i][j] = dp[i-1][j];
    17             if (a[i]>b[j] && max<dp[i-1][j])
    18                 max = dp[i-1][j];
    19             if(a[i] == b[j])
    20                 dp[i][j] = max + 1;
    21         }
    22     }
    23     max = 0;
    24     for(i=1;i<=m;i++)
    25         if(max<dp[n][i])
    26             max = dp[n][i];
    27     return max;
    28 }
    29 
    30 int main()
    31 {
    32     int i,j;
    33     cin>>t;
    34     while(t--)
    35     {
    36         cin>>n;
    37         for(i=1;i<=n;i++)
    38             cin>>a[i];
    39         cin>>m;
    40         for(j=1;j<=m;j++)
    41             cin>>b[j];
    42         memset(dp,0,sizeof(dp));
    43         cout<<LCIS()<<endl;
    44         if (t)
    45             cout<<endl;
    46     }
    47 }
    View Code

      其实还有一种更牛的方法是采用一维数组,但是时间还是n^2。当i循环到k的时候,原来dp[i]表示原来的dp[k][j],因为当a[i]!=b[j]的时候dp[i]的值是不变的,沿用过去的值就行了,只有当a[i]==b[j]的时候才需要更新dp[i]的值。

    代码如下:

     1 #include <iostream>
     2 using namespace std;
     3 int t,n,m;
     4 int a[503],b[503];
     5 int dp[503];
     6 
     7 int LCIS()
     8 {
     9     int i,j;
    10     int max;
    11     for(i=1;i<=n;i++)
    12     {
    13         max = 0;
    14         for(j=1;j<=m;j++)
    15         {
    16             if (a[i]>b[j] && max<dp[j])
    17                 max = dp[j];
    18             if(a[i] == b[j])
    19                 dp[j] = max + 1;
    20         }
    21     }
    22     max = 0;
    23     for(i=1;i<=m;i++)
    24         if(max<dp[i])
    25             max = dp[i];
    26     return max;
    27 }
    28 
    29 int main()
    30 {
    31     int i,j;
    32     cin>>t;
    33     while(t--)
    34     {
    35         cin>>n;
    36         for(i=1;i<=n;i++)
    37             cin>>a[i];
    38         cin>>m;
    39         for(j=1;j<=m;j++)
    40             cin>>b[j];
    41         memset(dp,0,sizeof(dp));
    42         cout<<LCIS()<<endl;
    43         if (t)
    44             cout<<endl;
    45     }
    46 }
    View Code
  • 相关阅读:
    Javascript 创建对象的三种方法及比较【转载+整理】
    Firebug Console Panel 控制台详解【转载+整理】
    解剖 CPU(另)
    解剖 CPU
    关于 URL 编码及 JavaScript 编码函数【转载+整理】
    基于用户投票的 6 个排名算法【转载+整理】
    奥巴马筹款网站的制作过程【转载+整理】
    CentOS 7.0关闭默认firewall防火墙启用iptables防火墙
    mybatis-generator 代码自动生成工具
    Linux中启动和停止jar包的运行
  • 原文地址:https://www.cnblogs.com/yazhou/p/3641721.html
Copyright © 2011-2022 走看看