From cccef832d9737e8cf0e22cfa9abeb567c7bb51c5 Mon Sep 17 00:00:00 2001 From: giles Date: Sun, 10 May 2026 05:58:05 +0000 Subject: [PATCH] ocaml: phase 5.1 manacher.ml baseline (longest palindrome "babadaba" = 7) Manacher's algorithm: insert # separators (length 2n+1) to unify odd/even cases, then maintain palindrome radii p[] alongside a running (center, right) pair to skip work via mirror reflection. Linear time. manacher "babadaba" = 7 (* witness: "abadaba", positions 1..7 *) Note: requires parenthesizing the if-expression on the rhs of <-: p.(i) <- (if pm < v then pm else v) Real OCaml parses bare `if` at <-rhs since the rhs is at expr level; our parser places <-rhs at binop level which doesn't include `if` / `match` / `let`. Workaround until we relax the binop RHS grammar. 149 baseline programs total. --- lib/ocaml/baseline/expected.json | 1 + lib/ocaml/baseline/manacher.ml | 32 ++++++++++++++++++++++++++++++++ plans/ocaml-on-sx.md | 10 ++++++++++ 3 files changed, 43 insertions(+) create mode 100644 lib/ocaml/baseline/manacher.ml diff --git a/lib/ocaml/baseline/expected.json b/lib/ocaml/baseline/expected.json index dae10217..0bd5832e 100644 --- a/lib/ocaml/baseline/expected.json +++ b/lib/ocaml/baseline/expected.json @@ -87,6 +87,7 @@ "lambda_calc.ml": 7, "lcs.ml": 4, "majority_vote.ml": 4, + "manacher.ml": 7, "levenshtein.ml": 11, "memo_fib.ml": 75025, "mortgage.ml": 1073, diff --git a/lib/ocaml/baseline/manacher.ml b/lib/ocaml/baseline/manacher.ml new file mode 100644 index 00000000..c80a250a --- /dev/null +++ b/lib/ocaml/baseline/manacher.ml @@ -0,0 +1,32 @@ +let manacher s = + let n = String.length s in + let m = 2 * n + 1 in + let t = Array.make m '#' in + for i = 0 to n - 1 do + t.(2 * i + 1) <- s.[i] + done; + let p = Array.make m 0 in + let center = ref 0 and right = ref 0 in + let max_p = ref 0 in + for i = 0 to m - 1 do + let mirror = 2 * !center - i in + if i < !right then begin + let v = !right - i in + let pm = p.(mirror) in + p.(i) <- (if pm < v then pm else v) + end; + while i + p.(i) + 1 < m && i - p.(i) - 1 >= 0 + && t.(i + p.(i) + 1) = t.(i - p.(i) - 1) do + p.(i) <- p.(i) + 1 + done; + if i + p.(i) > !right then begin + center := i; + right := i + p.(i) + end; + if p.(i) > !max_p then max_p := p.(i) + done; + !max_p + +;; + +manacher "babadaba" diff --git a/plans/ocaml-on-sx.md b/plans/ocaml-on-sx.md index b564e78a..e24a59e0 100644 --- a/plans/ocaml-on-sx.md +++ b/plans/ocaml-on-sx.md @@ -407,6 +407,16 @@ _Newest first._ binary search tree (`type 'a tree = Leaf | Node of 'a * 'a tree * 'a tree`) with insert + in-order traversal. Tests parametric ADT, recursive match, List.append, List.fold_left. +- 2026-05-10 Phase 5.1 — manacher.ml baseline (Manacher's longest + palindromic substring on "babadaba" = 7). Inserts `#` separators + to unify odd/even cases (string of length 2n+1), then maintains + palindrome radii in `p[]` plus a current rightmost-reach pair + (center, right). Linear time. The full input "babadaba" itself is + not a palindrome, but "abadaba" (positions 1..7) is — length 7. + Note: `p.(i) <- if pm < v then pm else v` requires explicit + parens — our parser doesn't accept `if` as the rhs of `<-` at + binop level (real OCaml does); workaround until we relax binop + RHS parsing. 149 baseline programs total. - 2026-05-10 Phase 5.1 — floyd_warshall.ml baseline (all-pairs shortest path on 4-node weighted graph, dist 0→3 = 9). Standard O(n³) DP: for each intermediate vertex k, relax all (i,j) pairs.