Problem solving series of linear dp

A longest rising sequence (LIS)

LIS (Longest Increasing Subsequence) rose longest sequence 
sequence a number of bi, when b1 <b2 <... <bS time, we call this sequence is rising.

For a given sequence (a1, a2, ..., aN), we can get some upside sequence (ai1, ai2, ..., aiK),

Where 1 <= i1 <i2 <...  <iK <= N.
For example, for the sequence (1, 7, 3, 5, 9, 4, 8), which rises some sequences, such as (1, 7), (3, 4, 8) and the like.

The longest sequence length is 4, such as the sequence (1, 3, 5, 8). 
Your job is for a given sequence, the length of the longest rise determined sequence.

Two Algorithms:

one:O(n^2):

State design: dp [i] representative for a [i] at the end of the LIS length 
state transition: dp [i] = max ( dp [i], dp [j] +1) (0 <= j <i, a [ j] <a [i]) 
boundary processing: dp [i] = 1 (  0 <= j <n)

Code:

 1 int LIS()
 2 {
 3     int ans=1;
 4     for(int i=1;i<=n;i++)
 5     {
 6         dp[i]=1;
 7         for(int j=1;j<i;j++)
 8         {
 9             if(a[i]>a[j])
10                 dp[i]=max(dp[i],dp[j]+1);
11         }
12     }
13     for(int i=1;i<=n;i++)
14         ans=max(ans,dp[i]);
15     return ans;
16 }

two: piggy-half +

a [i] denotes the i-th data. 
dp [i] represents the minimum length represented by LIS end of the element i + 1. 
Greedy idea for a rising sequence, it is clear the current last element of the smaller, the better to add new elements, such LIS natural length longer. 
Therefore, we only need to maintain dp array, which represents the minimum length of LIS is the end of the element i + 1, to ensure that each and every one minimum,

This way the length of the array is dp LIS length.

dp array of specific maintenance procedures is also an example to explain more clearly. 
For the same sequence a (1, 7, 3, 5, 9, 4, 8), dp change process is as follows:

  • dp [0] = a [0] = 1, the minimum length of the end of the LIS element did not have to pick a natural, is the first number. (Dp = {1})
  • For a [1] = 7, a [1]> dp [0], and therefore directly added to the end of dp, dp [1] = a [1]. (Dp = {1, 7})
  • For a [2] = 3, dp [0] <a [2] <dp [1], so a [2] Alternatively dp [1], so dp [1] = a [2], since the length of 2 LIS, the end of the element is naturally good 3 7 too, because the less it is a good follow-up to add a new element. (Dp = {1, 3})
  • For a [3] = 5, a [3]> dp [1], thus directly added to the end of dp, dp [2] = a [3]. (Dp = {1, 3, 5})
  • For a [4] = 9, a [4]> dp [2], thus also added directly to the end of dp, dp [3] = a [9]. (Dp = {1, 3, 5, 9})
  • For a [5] = 4, dp [1] <a [5] <dp [2], so a [5] Alternatively value of dp 5 [2], thus the length of the LIS 3, 4 will end elements better than 5, the smaller the better thing. (Dp = {1, 3, 4, 9})
  • For a [6] = 8, dp [2] <a [6] <dp [3], the same way a [6] Alternatively value dp 9 [3], the reason you know. (Dp = {1, 3, 5, 8})

Such sub-arrays to maintain complete dp, dp is the length of the required length of the array LIS 4. 
By solving the above, the array can be found dp is monotonically increasing, and therefore whether each of a [i], is determined to be directly inserted into the end of the array dp,

I.e., the maximum value of dp comparison with the last one, i.e., the array; if not, then find the position of the first dp greater than or equal a [i], and replaced with the a [i]. 
This process may utilize binary search, so the search time complexity is O (logN), so the total time complexity is O (N * logN)

 1 int LIS()
 2 {
 3     memset(dp,inf,sizeof(dp));
 4     int pos=0;
 5     dp[0]=a[0];
 6     for(int i=1;i<=n;i++)
 7     {
 8         if(a[i]>dp[pos])
 9             dp[++pos]=a[i];
10         else
11             dp[lower_bound(dp,dp+pos+1,a[i])-dp]=a[i];
12     }
13     return pos+1;
14 }

 

II. Longest common subsequence (LCS)

In two strings, some of the same characters, the sequence can be formed also may be equal, and therefore, the length of the longest word sequence of the longest common subsequence between the two is equal, the length of which can use dynamic programming to find .

 1 int LCS()
 2 {
 3     memset(dp,0,sizeof(dp));
 4     for(int i=1;i<=n;i++)
 5     {
 6         for(int j=1;j<=n;j++)
 7         {
 8             if(a[i-1]==b[j-1])
 9                 dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
10             else
11                 dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
12         }
13     }
14     return dp[n][n];    
15 }

III. Longest common subsequence rise (LCIS is)

one:O(n^3)

Analytical: f [i] [j] expressed as b [j] at the end, a maximum string length of the common subsequence increase a [i] before;
apparent: f [i] [j] > = f [i-1] [ j] ;;
recursion: If a [i] = b [j ]: f [i] [j] = f [i-1 [j!];
if a [i] == b [j ]: f [ i] [j] = max ( f [k] [j]) + 1; (1 <= k <= j-1 && b [j]> b [k])

 1 int LCIS()
 2 {
 3     int ans=0;
 4     for(int i=1;i<=n;i++)
 5     {
 6         for(int j=1;j<=n;j++)
 7         {
 8             if(a[i]!=b[j]) dp[i][j]=dp[i-1][j];
 9             else
10             {
11                 int maxx=0;
12                 for(int k=1;k<j;k++)
13                 {
14                     if(b[j]>b[k])
15                     maxx=max(maxx,dp[i-1][k]);
16                 }
17                 dp[i][j]=maxx+1;
18                 ans=max(dp[i][j],ans);
19             }
20         }
21     }
22     return ans;
23 }

 

two:O(n^2)

Optimization: For this a [i] and b [1-m] of the process of matching sequences mm maximum rise while the recording by the recording, update side, a reduced-dimensional

 1 void LCIS()
 2 {
 3     for(int i=1;i<=n;i++)
 4     {
 5         int maxx=0;
 6         for(int j=1;j<=n;j++)
 7         {
 8             dp[i][j]=dp[i-1][j];
 9             if(a[i]>b[j])
10                 maxx=max(maxx,dp[i-1][j]);
11             if(a[i]==b[j])
12                 dp[i][j]=maxx+1;
13         }
14     }
15     int ans=0;
16     for(int i=1;i<=n;i++)
17         ans=max(ans,dp[n][i]);
18     return ans;
19 }

 

Guess you like

Origin www.cnblogs.com/Spring-Onion/p/11355403.html