MCPcopy Create free account
hub / github.com/atomicdotdev/atomic / longest_increasing_subsequence

Function longest_increasing_subsequence

atomic-core/src/diff/patience.rs:227–273  ·  view source on GitHub ↗

Find the Longest Increasing Subsequence of matches by new_idx. Given matches sorted by old_idx, find the longest subsequence where new_idx values are strictly increasing. This ensures the matches maintain relative order in both sequences. Uses the O(N log N) algorithm with binary search.

(matches: &[UniqueMatch])

Source from the content-addressed store, hash-verified

225///
226/// Uses the O(N log N) algorithm with binary search.
227fn longest_increasing_subsequence(matches: &[UniqueMatch]) -> Vec<UniqueMatch> {
228 if matches.is_empty() {
229 return Vec::new();
230 }
231
232 let n = matches.len();
233
234 // tails[i] = index in matches of the smallest ending element of all
235 // increasing subsequences of length i+1
236 let mut tails: Vec<usize> = Vec::with_capacity(n);
237
238 // predecessors[i] = index of the predecessor of matches[i] in the LIS
239 let mut predecessors: Vec<Option<usize>> = vec![None; n];
240
241 for i in 0..n {
242 let new_idx = matches[i].new_idx;
243
244 // Binary search for the position to insert/replace
245 let pos = tails
246 .binary_search_by(|&j| matches[j].new_idx.cmp(&new_idx))
247 .unwrap_or_else(|x| x);
248
249 // Update predecessor
250 if pos > 0 {
251 predecessors[i] = Some(tails[pos - 1]);
252 }
253
254 // Update tails
255 if pos == tails.len() {
256 tails.push(i);
257 } else {
258 tails[pos] = i;
259 }
260 }
261
262 // Reconstruct the LIS by following predecessors
263 let mut lis = Vec::with_capacity(tails.len());
264 let mut current = tails.last().copied();
265
266 while let Some(idx) = current {
267 lis.push(matches[idx]);
268 current = predecessors[idx];
269 }
270
271 lis.reverse();
272 lis
273}
274
275/// Build the diff result using LIS anchors.
276///

Callers 6

patience_diff_recursiveFunction · 0.85
test_lis_simpleFunction · 0.85
test_lis_emptyFunction · 0.85
test_lis_singleFunction · 0.85
test_lis_all_increasingFunction · 0.85
test_lis_all_decreasingFunction · 0.85

Calls 6

cmpMethod · 0.80
lastMethod · 0.80
is_emptyMethod · 0.45
lenMethod · 0.45
pushMethod · 0.45
reverseMethod · 0.45

Tested by 5

test_lis_simpleFunction · 0.68
test_lis_emptyFunction · 0.68
test_lis_singleFunction · 0.68
test_lis_all_increasingFunction · 0.68
test_lis_all_decreasingFunction · 0.68