art-w / rmq

Range Minimum Query algorithms

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Given a preprocessed array, a Range Minimum Query (RMQ) returns the minimum element in a chosen subarray:

Find the minimum in a subarray

This library provides various implementations with different trade-offs:

Preprocessing and Memory Query
Naive O(1) O(N) No preprocessing
Dense O(N²) O(1) Precompute all queries
Sparse O(N logN) O(1) Precompute queries with a power-of-two length
Hybrid O(N) O(1) Combine Dense and Sparse to shave a log!
Segment O(N) O(logN) Binary partitioning of precomputed queries

benchmarks

Since RMQ is a useful building block for more advanced algorithms, this package exposes a low-level interface returning the index of the minimum element: online documentation

let arr = [| "b" ; "a" ; "d" ; "c" ; "e" ; "a" |] (* given an array *)
let min_array = Rmq.of_array ( <= ) arr (* configure its [min] function *)
module Impl = Rmq.Hybrid (* choose an RMQ implementation *)
let t = Impl.preprocess min_array (* to precompute some answers *)
let found_index = Impl.minimum_index min_array t ~i:2 ~len:3 (* query range [2..4] for its minimum *)
let () = assert (arr.(found_index) = "c")

As an example application, consider finding the Lowest Common Ancestor (LCA) between any two nodes in a tree:

  • An array of nodes is obtained by an in-order traversal of the tree from left to right (in dashed red)
  • The minimum element (by depth) between any two nodes in the array is their lowest common ancestor

LCA

When applied to a suffix tree, this yields a constant time "Longest Common Prefix (LCP)" between any substrings! (with linear preprocessing)

About

Range Minimum Query algorithms

License:MIT License


Languages

Language:OCaml 100.0%