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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/*!

[![](https://docs.rs/longest-increasing-subsequence/badge.svg)](https://docs.rs/longest-increasing-subsequence/)
[![](https://img.shields.io/crates/v/longest-increasing-subsequence.svg)](https://crates.io/crates/longest-increasing-subsequence)
[![](https://img.shields.io/crates/d/longest-increasing-subsequence.svg)](https://crates.io/crates/longest-increasing-subsequence)
[![Build Status](https://dev.azure.com/fitzgen/longest-increasing-subsequence/_apis/build/status/fitzgen.longest-increasing-subsequence?branchName=master)](https://dev.azure.com/fitzgen/longest-increasing-subsequence/_build/latest?definitionId=1&branchName=master)

## Longest Increasing Subsequence

> The longest increasing subsequence problem is to find a subsequence of a given
> sequence in which the subsequence's elements are in sorted order, lowest to
> highest, and in which the subsequence is as long as possible. This subsequence
> is not necessarily contiguous, or unique.

— [Wikipedia](https://en.wikipedia.org/wiki/Longest_increasing_subsequence)

For example, consider this sequence of integers:

> 2, 9, 4, 7, 3, 4, 5

The longest increasing subsequence (LIS) for this sequence is *2, 3, 4, 5*.

Note that there is not always a *singular* LIS. Consider this sequence:

> 2, 6, 5

In this sequence, both *2, 5* and *2, 6* are LISs.

## API

This crate exposes two functions for finding a longest increasing subsequence
within a slice:

1. The high-level, easy-to-use `lis` function takes any slice of `T: Ord` and
returns the LIS as a vector of indices into that slice.

2. The low-level `lis_with` function takes a custom comparator and lets you
bring your own allocations (which lets you choose to reuse allocations or use a
custom allocator).

Both functions use the same underlying algorithm. They execute in *O(n log n)*
time and use *O(n)* memory.

## Example

```
use longest_increasing_subsequence::lis;

let xs = vec![9, 2, 8, 3, 5];
for i in lis(&xs) {
    println!("{} at index {}", xs[i], i);
}

// Prints:
// 2 at index 1
// 3 at index 3
// 5 at index 4
```

 */

/// The high-level, easy-to-use function for finding a longest increasing
/// subsequence.
///
/// Takes any slice `&[T]` and uses the `T: Ord` implementation to determine the
/// LIS.
///
/// The LIS is returned as a vector of indices into the input items slice.
///
/// # Example
///
/// ```
/// use longest_increasing_subsequence::lis;
///
/// let xs = vec![9, 2, 8, 3, 5];
/// for i in lis(&xs) {
///     println!("{} at index {}", xs[i], i);
/// }
///
/// // Prints:
/// // 2 at index 1
/// // 3 at index 3
/// // 5 at index 4
/// ```
pub fn lis<T>(items: &[T]) -> Vec<usize>
where
    T: Ord,
{
    let mut seq = Vec::new();
    let p = &mut vec![0; items.len()];
    let m = &mut vec![0; items.len()];
    lis_with(items, &mut seq, |a, b| a < b, p, m);
    seq.reverse();
    seq
}

/// The low-level function for finding a longest increasing subsequence.
///
/// This low-level function allows you to:
///
/// * customize the comparator function to something other than `T: Ord`,
///
/// * bring your own allocations for the algorithm's temporary scratch space (so
/// you can reuse the same allocations across multiple `lis_with` calls, or use
/// a custom allocator, etc...),
///
/// * and collect the resulting LIS into a custom collection data structure.
///
/// Note that the `out_seq` is given the indices of the LIS in **reverse order**
/// from the end of the LIS first to the start of the LIS last.
///
/// ## Panics
///
/// Panics if `items`, `predecessors`, and `starts` do not all have the same
/// length.
///
/// ## Example
///
/// ```
/// use longest_increasing_subsequence::lis_with;
/// use std::collections::HashSet;
///
/// // Create allocations for the algorithm's scratch space.
/// let mut predecessors = Vec::new();
/// let mut starts = Vec::new();
///
/// // And a collection to contain the results.
/// let mut results = HashSet::new();
///
/// // A slice whose LIS we would like to find.
/// let xs = vec![9, 2, 8, 3, 5];
///
/// // Ensure our allocations have enough space.
/// predecessors.resize_with(xs.len(), Default::default);
/// starts.resize_with(xs.len(), Default::default);
///
/// lis_with(
///     &xs,
///     &mut results,
///     |a, b| a < b,
///     &mut predecessors,
///     &mut starts,
/// );
///
/// assert_eq!(results, vec![1, 3, 4].into_iter().collect());
///
/// // Another slice whose LIS we would like to find.
/// let ys = vec![9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
///
/// // We are going to reuse our previous scratch space. Again, ensure we
/// // have enough space.
/// predecessors.resize_with(ys.len(), Default::default);
/// starts.resize_with(ys.len(), Default::default);
///
/// results.clear();
/// lis_with(
///     &ys,
///     &mut results,
///     |a, b| a < b,
///     &mut predecessors,
///     &mut starts,
/// );
///
/// assert_eq!(results, vec![9, 10, 11, 12, 13, 14, 15, 16, 17, 18].into_iter().collect());
/// ```
pub fn lis_with<T, S, F>(
    items: &[T],
    out_seq: &mut S,
    mut less_than: F,
    predecessors: &mut [usize],
    starts: &mut [usize],
) where
    S: Extend<usize>,
    F: FnMut(&T, &T) -> bool,
{
    assert_eq!(items.len(), predecessors.len());
    assert_eq!(predecessors.len(), starts.len());

    if items.is_empty() {
        return;
    }

    unsafe {
        let mut k = 0;
        let len = items.len();

        for i in 0..len {
            let j = *get_unchecked(starts, k);

            if less_than(get_unchecked(items, j), get_unchecked(items, i)) {
                set_unchecked(predecessors, i, j);
                k += 1;
                set_unchecked(starts, k, i);
                continue;
            }

            let mut lo = 0;
            let mut hi = k;

            while lo < hi {
                // Get the mid point while handling overflow.
                let mid = (lo >> 1) + (hi >> 1) + (lo & hi & 1);
                if less_than(
                    get_unchecked(items, *get_unchecked(starts, mid)),
                    get_unchecked(items, i),
                ) {
                    lo = mid + 1;
                } else {
                    hi = mid;
                }
            }

            if less_than(
                get_unchecked(items, i),
                get_unchecked(items, *get_unchecked(starts, lo)),
            ) {
                if lo > 0 {
                    set_unchecked(predecessors, i, *get_unchecked(starts, lo - 1));
                }
                set_unchecked(starts, lo, i);
            }
        }

        let u = k + 1;
        let mut v = *get_unchecked(starts, k);
        out_seq.extend((0..u).rev().map(|_| {
            let w = v;
            v = *get_unchecked(predecessors, v);
            w
        }));
    }
}

#[inline(always)]
unsafe fn get_unchecked<T>(slice: &[T], index: usize) -> &T {
    debug_assert!(index < slice.len());
    slice.get_unchecked(index)
}

#[inline(always)]
unsafe fn set_unchecked<T>(slice: &mut [T], index: usize, value: T) {
    debug_assert!(index < slice.len());
    *slice.get_unchecked_mut(index) = value;
}