最长递增子序列总结

传统写法:

string str;
        int count=0;
        cin>>str;
        int a[200];
        a[0]=-999; //必须赋不属于str[i]的值
        for(int i=0;i<str.length();++i)
            for(int j=count;j>=0;j--) //一个一个遍历维护a[j]的最小值
                if((int)str[i]>a[j])
                {
                    a[j+1]=str[i];
                    if(j+1==count+1) 
                        count++;
                    break;
                }
        cout<<count<<endl;

二分的严格递增子序列的写法:

       
        string a;
        char b[10005]; //b[i]为了a字符串存在的,存储长度为i的最小字符
        b[1]=a[0];
        int len=1,l,r,mid;
        for(i=1;i<a.length();++i)
        {
            l=1,r=len;
            bool jud=0;
            /*b串绝对是递增的*/
            while(l<=r) //2分的写法一般是用于非严格递增的序列或者数据量十分爆炸的序列
            {
                mid=(l+r)/2;
                if(b[mid]<a[i]) l=mid+1;  
                else if(b[mid]>a[i]) r=mid-1;
                else  //如果找到相同的,则不需要对已有的b串进行改动
                {
                    jud=1;
                    break;
                }
            }
            if(!jud)
            {
              b[l]=a[i]; //二分每次都返回刚好比要寻找的值大的数的下标,更新b[l]
              if(l>len) len=l;
            }
        }
        printf("%d\n",len);

 

二分的非严格递增子序列的写法:

        d[0]=-1;
        d[1]=S[0];
        int len=1,l,r,mid;
        for(int i=1;i<n;++i)
        {
            l=0,r=len;
            while(l<=r)
            {
                mid=(l+r)>>1;
                if(d[mid]<=S[i]) l=mid+1;
                else r=mid-1;
            }
            d[l]=S[i];
            if(l>len) len++;
        }

高端写法:

        top1=top2=0;
        int num=remove(y,y+MAX,0)-y;//去0
        for(int i=0;i!=num;i++)
        {
            int *p=lower_bound(tmp,tmp+top1,y[i]);//二分,返回下标
            int *q=lower_bound(tmp2,tmp2+top2,y[i],greater<int>());
            if(p-tmp==top1) ++top1; //最长递增
            if(q-tmp2==top2) ++top2; //最长递减
            *p=y[i];
            *q=y[i];
        }

 

posted @ 2013-04-30 21:54  小仪在努力~  阅读(180)  评论(0编辑  收藏  举报