ExamplesBy LevelBy TopicLearning Paths
820 Advanced

Manacher's Algorithm — Longest Palindromic Substring

Functional Programming

Tutorial Video

Text description (accessibility)

This video demonstrates the "Manacher's Algorithm — Longest Palindromic Substring" functional Rust example. Difficulty level: Advanced. Key concepts covered: Functional Programming. Finding the longest palindromic substring naively requires O(n^2) time by expanding from each center. Key difference from OCaml: | Aspect | Rust | OCaml |

Tutorial

The Problem

Finding the longest palindromic substring naively requires O(n^2) time by expanding from each center. Manacher's algorithm finds all palindromic substrings — both odd and even length — in O(n) time by reusing previously computed palindrome radii. This is the canonical O(n) solution to "find the longest palindrome in a string," a classic interview problem with practical applications in DNA analysis (palindromic sequences indicate restriction enzyme sites), text compression, and symmetry detection. The key insight is that palindromes inside a larger known palindrome have known minimum radii, avoiding redundant character comparisons.

🎯 Learning Outcomes

  • • Transform the string with sentinel characters (#) to unify odd/even length palindrome handling
  • • Understand the center/right-boundary invariant: track the palindrome extending furthest right
  • • Use the mirror property: p[mirror] = p[i] (limited by the right boundary) as a starting point
  • • Implement the O(n) linear scan with the amortized argument for why each character is visited O(1) times
  • • Recover substring positions from the transformed string's palindrome radius array
  • Code Example

    #![allow(clippy::all)]
    //! Placeholder

    Key Differences

    AspectRustOCaml
    Transformationflat_map + onceBuffer with character appending
    Radius arrayVec<usize>int array
    Center/right stateTwo usize variablesint ref pair
    Result extractionp.iter().enumerate().max_by_key()Array.fold_left for max
    Char handlingchars() for UnicodeUchar or byte-level
    Sentinel choice# (not in typical ASCII text)Same; often \000 for bytes

    OCaml Approach

    OCaml implements the transformation with Buffer, appending '#' between and around each character. The palindrome radius array is Array.make (2*n+1) 0. Center and right boundary are mutable int ref values. OCaml's pattern matching elegantly handles the three cases: mirror palindrome fits entirely within boundary, mirror radius equals boundary distance, or expansion needed. The String.sub at the end extracts the longest palindromic substring from the original coordinates.

    Full Source

    #![allow(clippy::all)]
    //! Placeholder

    Deep Comparison

    OCaml vs Rust: Manacher Palindrome

    Overview

    See the example.rs and example.ml files for detailed implementations.

    Key Differences

    AspectOCamlRust
    Type systemHindley-MilnerOwnership + traits
    MemoryGCZero-cost abstractions
    MutabilityExplicit refmut keyword
    Error handlingOption/ResultResult<T, E>

    See README.md for detailed comparison.

    Exercises

  • Return all palindromic substrings (not just the longest) sorted by length descending.
  • Count the total number of distinct palindromic substrings using the Manacher array.
  • Find the minimum number of cuts to partition a string into palindromes (use Manacher for O(n) palindrome detection + DP).
  • Implement Eertree (palindromic tree) as an alternative data structure and compare with Manacher.
  • Extend to report palindromes of a minimum length k efficiently without O(n) post-processing.
  • Open Source Repos