最长上升子序列LIS算法粗略讲解

来源:互联网 发布:工程数据的内涵 编辑:程序博客网 时间:2024/05/16 09:48

定义

LIS(Longest Increasing Subsequence)最长上升(不下降)子序列,有两种算法复杂度为O(n*logn)和O(n^2)。在上述算法中,若使用朴素的顺序查找在D1..Dlen查找,由于共有O(n)个元素需要计算,每次计算时的复杂度是O(n),则整个算法的时间复杂度为O(n^2),与原来算法相比没有任何进步。但是由于D的特点(2),在D中查找时,可以使用二分查找高效地完成,则整个算法时间复杂度下降为O(nlogn),有了非常显著的提高。需要注意的是,D在算法结束后记录的并不是一个符合题意的最长上升子序列!算法还可以扩展到整个最长子序列系列问题。

问题描述:给出一个序列a1,a2,a3,a4,a5,a6,a7….an,求它的一个子序列(设为s1,s2,…sn),使得这个子序列满足这样的性质,s1

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <map>#include <cmath>#include <queue>using namespace std;const int maxn=1e3+10;int n,a[maxn],dp[maxn];int main(){    while(~scanf("%d",&n))    {        for(int i=0;i<n;i++)        {            scanf("%d",a+i);            dp[i]=1;        }          for(int i=1;i<n;i++)          {              for(int j=0;j<i;j++)              {                  if(a[i]>a[j])                  {                      dp[i]=max(dp[i],dp[j]+1);                  }              }          }          int maxi=0;          for(int i=0;i<n;i++)          {           printf("sss  i=%d   dp[i]=%d\n",i,dp[i]);              maxi=max(maxi,dp[i]);          }          printf("%d\n",maxi);    }    return 0;}

(nlogn):维护一个一维数组c,并且这个数组是动态扩展的,初始大小为1,c[i]表示最长上升子序列长度是i的所有子串中末尾最小的那个数,根据这个数字,我们可以比较知道,只要当前考察的这个数比c[i]大,那么当前这个数一定能通过c[i]构成一个长度为i+1的上升子序列。当然我们希望在C数组中找一个尽量靠后的数字,这样我们得到的上升子串的长度最长,查找的时候使用二分搜索,这样时间复杂度便下降了。

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <map>#include <cmath>#include <queue>using namespace std;int n,a[40005],dp[40005],b[40005];int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(int i=1;i<=n;i++)        {            scanf("%d",&a[i]);            dp[i]=1;        }        int l,r,mid,maxi=0,len=0;        for(int i=1;i<=n;i++)        {            int num=a[i];            l=1;            r=len;            while(l<=r)            {              mid=(l+r)>>1;              if(num>b[mid])                 l=mid+1;              else                 r=mid-1;            }            b[l]=num;            dp[i]=l;            if(l>len)                len=l;            if(dp[i]>maxi)                maxi=dp[i];        }            printf("%d\n",maxi);    }    return 0;}

END!!!!!!!!!!!!!!!!!!!

1 0
原创粉丝点击