Longest ascending subsequence lis solution (n^n && Nlogn)

Source: Internet
Author: User

The longest increment subsequence problem in a column number to find some number satisfies any two number a[i] and a[j] If i<j must have a[i]<a[j] such longest subsequence is called the longest increment subsequence lis

There are two common methods to solve LIS problem, a time complexity n^n a time complexity Nlogn

Now, let's start with the n^n algorithm.

Set Dp[i] Indicates the length of the longest ascending sub-sequence ending with I the decomposition of the problem into the sequence of the maximum ascending subsequence of each of the most end-points, starting from the second item, and then finding the largest one is the answer. The state transfer equation is

Dp[i] = max{dp[j]+1}, 1<=j<i,a[j]<a[i].

Code Time Reference POJ2533

#include <iostream> #include <cstdio> #include <cstring>using namespace std;const int maxn = 1011;int an [Maxn];int dp[maxn];int Res;int Main () {    int n;    scanf ("%d", &n);    for (int i = 1; I <= n; ++i) {        scanf ("%d", &an[i]);    }    for (int i = 1; I <= n; ++i) {        dp[i] = 1;        for (int j = 1; j < i; ++j) {            if (An[j] < An[i]) {                dp[i] = max (Dp[i], dp[j] + 1);            }        }        res = max (Dp[i], res);    }    printf ("%d\n", res);    return 0;}


Let's take a look at another more efficient algorithm time complexity Nlogn

Suppose there is a sequence a[1..9] = 2 1 5 3 6 4 8 9 7 It can be seen that its LIS length is 5

We define a sequence DP and then let i = 1 to 9 examine the sequence

We'll use a variable len to record how long it's going to be.

First put a[1] into DP dp[1] = 2 that is, when there is only 11 digits 2, the minimum end of the LIS with length 1 is 2 then len=1

Then put a[2] in the order of the DP dp[1] = 1 that is, the smallest end of the LIS with a length of 1 is 1 a[1]=2 It's useless, it's easy to understand. Then Len=1

Then a[3] = 5 A[3]>dp[1] So dp[1+1]=dp[2]=a[3]=5 means that the minimum end of the LIS with a length of 2 is 5 this time dp[1..2] = 1 5 len=2

Again a[4] = 3 It just adds 1, 5 is placed in the position of 1 is obviously inappropriate because 1 is less than 3 of the length of the LIS minimum end should be 1 so it is easy to infer the length of the LIS minimum of 1 is 2 so you can eliminate 3 this time dp[1..2] = 5, 1 len = 3

Continue a[5] = 6 it after 3 because dp[2] = 3 and 6 after 3 so it is easy to infer dp[3] = 6 then dp[1..3] = 1, 3, 6, still easy to understand len = 3

6th A[6] = 4 You see it between 3 and 6 so we can replace 6 to get dp[3] = 4 dp[1..3] = 1, 3, 4 len continues to be equal to 3

7th A[7] = 8 It's much bigger than 4 mm so dp[4] = 8 Len becomes 4.

8th A[8] = 9 get dp[5] = 9 Len continues to grow to 5.

Last a[9] = 7 It is between dp[3] = 4 and dp[4] = 8 so we know the latest dp[4] =7 dp[1..5] = 1, 3, 4, 7, 9 len = 5

So we know that the LIS has a length of 5

Note that this 1,3,4,7,9 is not an LIS, it just stores the corresponding length of the LIS minimum end with this end we can insert the data one by one although the last a[9] = 7 update is not meaningful for this set of data but if there are two numbers 8 and 9 then you can update the 8 to A[5] 9 updated to a[6] The length of the LIS is 6

And then we should find something. Inserting data into a DP is ordered and replaced without moving--that is, we can use a binary search to optimize the insertion time of each number to O (logn) ~~~~~ so the time complexity of the algorithm is reduced to O (NLOGN)!

Attach the code implementation first HDU1950 more general wording

#include <iostream> #include <cstdio> #include <cstring>using namespace std;const int maxn = 40010;int AN[MAXN], DP[MAXN], Ans;int main () {    int t;    scanf ("%d", &t);    while (t--) {        int n;        scanf ("%d", &n);        for (int i = 1; I <= n; ++i) {            scanf ("%d", &an[i]);        }        DP[1] = an[1];        ans = 1;        for (int i = 2; I <= n; ++i) {            int st = 1;            int en = ans + 1;            while (St < en) {                int mi = (st+en)/2;                if (An[i] <= Dp[mi]) {                    en = mi;                }                else{                    st = mi + 1;                }            }            Dp[en] = An[i];            if (en = = ans + 1) {                ++ans;            }        }        printf ("%d\n", ans);    }    return 0;}

The next thing you learned in the challenge is to use the lower_bound to achieve the two-point problem is still POJ2553

#include <iostream> #include <cstdio> #include <cstring> #include <algorithm>using namespace std;const int MAXN = 1011;const int inf = 0xffffff;int an[maxn];int dp[maxn];int main () {    int n;    scanf ("%d", &n);    for (int i = 0; i < n; ++i) {        scanf ("%d", &an[i]);    }    Fill (DP, dp+n, INF);    for (int i = 0; i < n; ++i) {        *lower_bound (DP, Dp+n, an[i]) = An[i];    }    printf ("%d\n", Lower_bound (DP, DP+N, INF)-DP);    return 0;}



Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Longest ascending subsequence lis solution (n^n && Nlogn)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.