Dynmamic Programming: LCIS (Longest Common Increasing Sequence)
For two sequences A and B, find length of the longest common increasing subsequence.
The length of sequence A and B does not exceed 3000.
Input format The first line contains an integer N, which represents the length of the sequence A and B.
The second row contains N integers, representing the sequence A.
The third row contains N integers, representing the sequence B.
Output format Output an integer that represents the length of the longest common increasing sequence.
data range 1 ≤ N≤ 3000, None of the numbers in the sequence exceed231− 1 Input sample:
4
2 2 1 3
2 1 2 3
Sample output:
2
State representation:
- f[i][j] is the length of LCIS in a[1 ~ i] and b[1 ~ j] ending with b[j]
State calculation:
We can first loop through i and j to get a matching pair of a[i] and b[j]. Once we have found them, we then need to find the LCIS ending with the value b[j]. We can do this by looping through all previous DP values of numbers with an array b index less than j, denoted as “k”. If the value at b[k] is less than the value of b[j], we can assume b[j] can be added to the end of the sequence and creating a new LCIS of length f[i - 1][k] + 1 (the longest possible length ending with b[k] and adding 1 for b[j]).
If implemented directly according to the above ideas, a three-fold loop is required:
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= n; j ++ )
{
f[i][j] = f[i - 1][j];
if (a[i] == b[j])
{
int maxv = 1;
for (int k = 1; k < j; k ++ )
if (a[i] > b[k])
maxv = max(maxv, f[i - 1][k] + 1);
f[i][j] = max(f[i][j], maxv);
}
}
}
Optimization:
We can change our program from three for loops (O(N^3)) to two (O(N^2)) by realizing that we don’t need to visit all of the previous values “k” to get the maxv. Because the implementation involved is DP, for every new value of j we can reuse the previously calculated maxv value instead of looping through all previous values again in k.
The final answer enumeration subsequence ends with the maximum value.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <bits/stdc++.h>
using namespace std;
const int N = 3005;
int n;
int a[N], b[N];
int f[N][N];
int g[N][N];
int main() {
cin >> n;
for (int i = 1; i <= n; ++ i) cin >> a[i];
for (int j = 1; j <= n; ++ j) cin >> b[j];
for (int i = 1; i <= n; ++ i) {
int maxv = 1;
for (int j = 1; j <= n; ++ j) {
f[i][j] = f[i - 1][j];
if (a[i] == b[j])
f[i][j] = max(f[i][j], maxv);
if (a[i] > b[j])
maxv = max(maxv, f[i - 1][j] + 1);
}
}
int ans = 0;
for (int i = 1; i <= n; ++ i) ans = max(f[n][i], ans);
cout << ans << "\n";
return 0;
}