LIS and dilworth

Posted on 2021-09-22 20:44  chen—  阅读(80)  评论(0)    收藏  举报

首先,先明白子串子序列之间的差别:

以字符串 abcdefgh 为例:

1. 字符子串指的是字符串中连续的字符 

   eg. abc, efg····

2. 字符子序列指的是字符串中先后顺序一致但不一定连续的字符  

   eg. adg, cdgh····

   可以去掉字符串中的部分字符,但不可改变其前后顺序。

 

最长上升子序列(LIS

序列(1, 7, 3, 5, 9, 4, 8) ,其最长上升子序列长度为4,其中一条LIS(1,3,5,8)

ps.与最长非降序子序列(二者区别就是序列中是否可以有相等的数)同理。

要用集合的观念来理解此类问题:

子序列、公共子序列以及最长公共子序列都不唯一

对于固定的数组,虽然LIS序列不一定唯一,但LIS的长度是唯一的

 

解决方案:

采用贪心+二分 O(nlogn)

由贪心的思想:对于一个上升子序列,显然其结尾元素越小,越有利于在后面接其他的元素,也就越可能变得更长。

只需要维护一个low数组,具体情况:

1. 如果读入的数x > low[end],就将x读入到low的末尾

2. x <= low[end], 就用x来更新low,由于采用这样的做法low中插入的数据都是有序的,一定都是单调递增(单调不减也可以),就可以采用二分查找的方法lower_bound( )来找到第一个大于等于x的数,并用x来取代low中的数,本质是贪心算法的体现。

3. 可以发现只用步骤(1)可以增加LIS的长度,而步骤(2)的目的在于贪心为接下来的操作做铺垫

4. 注意!low中单序列并不一定是正确的最长上升子序列,该做法只能得到LIS的长度,并不一定能得到正确的LIS序列,因为二分插入数字的,有可能将排序较后的数插在排序比它前的数的前面,这样的序列就不满足有序了

   但是这样做的依据是二分查找插入并没有改变LIS的长度,这一步的意义更在于贪心的思想,即代表一种可能性,为之后的更新做了铺垫。

   总之low并不一定表示最长上升子序列,它只表示相应最长子序列长度的排好序的最小序列,它可以反映LIS的长度。

借鉴博客

 

code:

//核心代码1
const int MAXN;
int a[MAXN]
int low[MAXN];
int main(){
    int n;
    cin >> n;
    memset(low,0x3f,sizeof low);
    for(int i=0;i<n;i++)
        cin >> a[i];
    low[1] = a[1];
    int num = 1;
    for(int i=1;i<n;i++){
        if(a[i] > low[num])
            low[++num] = a[i];
        else
            二分查找
            low[ ] = a[i];
    }
    cout << num;
    return 0;
}
//代码2   STL实现
#include<iostream>
#include<vector> 
using namespace std;
const int MAXN = 1e5+10;
int a[MAXN];
vector<int> vec;
int main(){
    int n;
    cin >> n;
    for(int i=1;i<=n;i++)
        cin >> a[i];
    for(int i=1;i<=n;i++){
        if(vec.empty() || a[i]>vec.back())
            vec.push_back(a[i]);
        else{
            int pos = lower_bound(vec.begin(),vec.end(),a[i])-vec.begin();
            vec[pos] = a[i];
        }
    } 
    cout << vec.size();
    return 0;
}

扩展运用:

狄尔沃斯定理(Dilworth's theorem)

百度百科:亦称偏序集分解定理,是关于偏序集的极大极小的定理,该定理断言:对于任意有限偏序集,其最大反链中元素的数目必等于最小链划分中链的数目。此定理的对偶形式亦真,它断言:对于任意有限偏序集,其最长链中元素的数目必等于其最小反链划分中反链的数目,由偏序集P按如下方式产生的图G称为偏序集的可比图:G的节点集由P的元素组成,而e为G中的边,仅当e的两端点在P中是可比较的,有限全序集的可比图为完全图

point 1:对于任意有限偏序集,其最大反链中元素的数目必等于最小链划分中链的数目。

point 2:对偶形式亦真,断言:对于任意有限偏序集,其最长链中元素的数目必等于其最小反链划分中反链的数目

point 3:最小链覆盖(使链最少)= 最长反链长度 = 偏序集宽度
    最小反链覆盖 = 最长链长度 = 偏序集深度

栗子:

1 2 3 2 3

要把 1 2 3 2 3 从序列变为集合(p,v)的形式{(1,2),(2,2),(3,3),(4,2),(5,3)},第一个是序数第二个是对应的数,并在此基础上定义关系 <=:pi<=pj&&vi<=vj。

最*小*上升子序列划分个数 {1,2,2,3}与{3}       —— 两个
等于最*长”反链长度 (3,2)                     ——同样是两个

反之则是
最小反链划分{1} ,{2} ,{3,2},{3}             ——4个
等于最长不降子序列长度 {1,2,2,3}             ——同样4个
假如是最长上升子序列 就定义关系为 <:pi<pj&&vi<vj即可

例题:

样例结果:

4条轨道的列车:

8 4 2 1

5 3

6 9

7

其LIS为

 2 3 6 7

长度为4

终上所述,采用上面分析的代码就可以AC此题