Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
LIS.H
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
31
45# ifndef LIS_H
46# define LIS_H
47
48# include <algorithm>
49# include <cstddef>
50# include <limits>
51# include <utility>
52
53# include <ahFunction.H>
54# include <tpl_array.H>
55
56namespace Aleph
57{
59 template <typename T>
61 {
62 size_t length = 0;
64 };
65
66 namespace lis_detail
67 {
68 template <typename T, class Compare>
69 [[nodiscard]] inline size_t
70 lower_bound_pos(const Array<T> & tails, const T & value, Compare cmp)
71 {
72 size_t lo = 0, hi = tails.size();
73 while (lo < hi)
74 {
75 const size_t mid = lo + (hi - lo) / 2;
76 if (cmp(tails[mid], value))
77 lo = mid + 1;
78 else
79 hi = mid;
80 }
81 return lo;
82 }
83
84 template <typename T, class Compare>
85 [[nodiscard]] inline size_t
86 upper_bound_pos(const Array<T> & tails, const T & value, Compare cmp)
87 {
88 size_t lo = 0, hi = tails.size();
89 while (lo < hi)
90 {
91 const size_t mid = lo + (hi - lo) / 2;
92 if (cmp(value, tails[mid]))
93 hi = mid;
94 else
95 lo = mid + 1;
96 }
97 return lo;
98 }
99 } // namespace lis_detail
100
101
113 template <typename T, class Compare = Aleph::less<T>>
116 Compare cmp = Compare())
117 {
118 const size_t n = seq.size();
119 if (n == 0)
120 return LIS_Result<T>{0, Array<T>()};
121
122 // tails[i] = smallest tail element for IS of length i+1
124 tails.reserve(n);
125
126 // parent[i] = index of predecessor of seq[i] in best IS ending at seq[i]
128 // pos[i] = index in seq of the element at tails[i]
130 tail_idx.reserve(n);
131
132 for (size_t i = 0; i < n; ++i)
133 {
134 const size_t lo = lis_detail::lower_bound_pos(tails, seq[i], cmp);
135
136 if (lo == tails.size())
137 {
138 tails.append(seq[i]);
139 tail_idx.append(i);
140 }
141 else
142 {
143 tails[lo] = seq[i];
144 tail_idx[lo] = i;
145 }
146
147 parent(i) = lo > 0 ? tail_idx[lo - 1]
148 : std::numeric_limits<size_t>::max();
149 }
150
151 // reconstruct
152 const size_t lis_len = tails.size();
154 size_t idx = tail_idx[lis_len - 1];
155 for (size_t k = lis_len; k > 0; --k)
156 {
157 result(k - 1) = seq[idx];
158 idx = parent(idx);
159 }
160
161 return LIS_Result<T>{lis_len, std::move(result)};
162 }
163
164
176 template <typename T, class Compare = Aleph::less<T>>
177 [[nodiscard]] size_t
178 lis_length(const Array<T> & seq, Compare cmp = Compare())
179 {
180 const size_t n = seq.size();
181 if (n == 0)
182 return 0;
183
185 tails.reserve(n);
186
187 for (size_t i = 0; i < n; ++i)
188 {
189 const size_t lo = lis_detail::lower_bound_pos(tails, seq[i], cmp);
190
191 if (lo == tails.size())
192 tails.append(seq[i]);
193 else
194 tails[lo] = seq[i];
195 }
196
197 return tails.size();
198 }
199
200
214 template <typename T, class Compare = Aleph::less<T>>
217 Compare cmp = Compare())
218 {
219 const size_t n = seq.size();
220 if (n == 0)
221 return LIS_Result<T>{0, Array<T>()};
222
224 tails.reserve(n);
225
228 tail_idx.reserve(n);
229
230 for (size_t i = 0; i < n; ++i)
231 {
232 const size_t pos = lis_detail::upper_bound_pos(tails, seq[i], cmp);
233
234 if (pos == tails.size())
235 {
236 tails.append(seq[i]);
237 tail_idx.append(i);
238 }
239 else
240 {
241 tails[pos] = seq[i];
242 tail_idx[pos] = i;
243 }
244
245 parent(i) = pos > 0 ? tail_idx[pos - 1]
246 : std::numeric_limits<size_t>::max();
247 }
248
249 const size_t len = tails.size();
250 Array<T> result = Array<T>::create(len);
251 size_t idx = tail_idx[len - 1];
252 for (size_t k = len; k > 0; --k)
253 {
254 result(k - 1) = seq[idx];
255 idx = parent(idx);
256 }
257
258 return LIS_Result<T>{len, std::move(result)};
259 }
260} // namespace Aleph
261
262# endif // LIS_H
Standard functor implementations and comparison objects.
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:139
static Array create(size_t n)
Create an array with n logical elements.
Definition tpl_array.H:194
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:351
void reserve(size_t cap)
Reserves cap cells into the array.
Definition tpl_array.H:315
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4118
size_t lower_bound_pos(const Array< T > &tails, const T &value, Compare cmp)
Definition LIS.H:70
size_t upper_bound_pos(const Array< T > &tails, const T &value, Compare cmp)
Definition LIS.H:86
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
LIS_Result< T > longest_nondecreasing_subsequence(const Array< T > &seq, Compare cmp=Compare())
Compute the Longest Non-Decreasing Subsequence.
Definition LIS.H:216
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
LIS_Result< T > longest_increasing_subsequence(const Array< T > &seq, Compare cmp=Compare())
Compute the Longest Increasing Subsequence (patience sorting).
Definition LIS.H:115
size_t lis_length(const Array< T > &seq, Compare cmp=Compare())
Compute only the length of the LIS (no reconstruction).
Definition LIS.H:178
Result of a LIS computation.
Definition LIS.H:61
Array< T > subsequence
One optimal LIS.
Definition LIS.H:63
size_t length
Length of the LIS.
Definition LIS.H:62
static int * k
Dynamic array container with automatic resizing.