ExamplesBy LevelBy TopicLearning Paths
819 Fundamental

Z-Algorithm String Matching

Functional Programming

Tutorial Video

Text description (accessibility)

This video demonstrates the "Z-Algorithm String Matching" functional Rust example. Difficulty level: Fundamental. Key concepts covered: Functional Programming. The Z-algorithm computes, for each position in a string, the length of the longest substring starting at that position that is also a prefix of the whole string. Key difference from OCaml: | Aspect | Rust | OCaml |

Tutorial

The Problem

The Z-algorithm computes, for each position in a string, the length of the longest substring starting at that position that is also a prefix of the whole string. This Z-array answers pattern matching questions directly: concatenate pattern + "$" + text, compute the Z-array, and any position where Z[i] equals the pattern length is a match. The algorithm runs in O(n) time and O(n) space, making it a linear alternative to KMP with a simpler conceptual model. It powers prefix-related string queries in competitive programming, bioinformatics repeat analysis, and text compression preprocessing.

🎯 Learning Outcomes

  • • Understand the Z-box (l, r) maintenance: a window tracking the rightmost known matching prefix
  • • Implement O(1) amortized extension using the existing Z-box to skip recomputation
  • • Recognize the pattern matching reduction: P + $ + T → find positions where Z[i] == |P|
  • • Learn the difference from KMP failure function: Z measures prefix matches at each position directly
  • • Apply Z-array to: string periods, pattern counting, lexicographically smallest rotation
  • Code Example

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

    Key Differences

    AspectRustOCaml
    Input type&[u8] — byte slicebytes or string
    Z-box stateTwo usize variablesint ref or threaded recursion
    Concatenation[pattern, b'$', text].concat()Bytes.concat
    Bound checksDebug-mode auto-checksBytes.get raises exception
    Result filterenumerate().filter()Array.to_seq \|> Seq.filter_mapi
    Separator byteMust not appear in inputSame constraint

    OCaml Approach

    OCaml implements the Z-function with mutable int ref for l and r, or threads them through a tail-recursive loop. Bytes.get provides O(1) character access. The Array.make n 0 creates the Z-array. OCaml's pattern matching on the Z-box condition i < r maps cleanly to if i < !r then. For string matching, Bytes.concat Bytes.empty [pattern; sep; text] creates the concatenated input. The result scan Array.to_seq |> Seq.filter_mapi finds positions where Z equals pattern length.

    Full Source

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

    Deep Comparison

    OCaml vs Rust: Z Algorithm

    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

  • Use the Z-array to find the shortest period of a string (smallest k such that the string is made of repeating k-length prefix).
  • Find all occurrences of a pattern in text and return start/end pairs using the Z-function approach.
  • Implement lexicographically smallest rotation: find i that minimizes s[i..] + s[..i].
  • Compare Z-algorithm and KMP on identical inputs and verify they produce consistent results.
  • Use the Z-array to count distinct substrings that are prefixes of the string.
  • Open Source Repos