type trie = { mutable terminal : bool; mutable children : (char * trie) list }

let make_trie () = { terminal = false; children = [] }

let rec lookup_child cs c =
  match cs with
  | [] -> None
  | (k, v) :: rest -> if k = c then Some v else lookup_child rest c

let rec insert t s i =
  if i = String.length s then t.terminal <- true
  else
    let c = s.[i] in
    match lookup_child t.children c with
    | Some child -> insert child s (i + 1)
    | None ->
      let nc = make_trie () in
      t.children <- (c, nc) :: t.children;
      insert nc s (i + 1)

let rec contains t s i =
  if i = String.length s then t.terminal
  else
    let c = s.[i] in
    match lookup_child t.children c with
    | Some child -> contains child s (i + 1)
    | None -> false

;;

let t = make_trie () in
List.iter (fun w -> insert t w 0) ["cat"; "car"; "card"; "cart"; "dog"; "doge"];
let count = ref 0 in
List.iter (fun w -> if contains t w 0 then count := !count + 1)
  ["cat"; "car"; "ca"; "card"; "cart"; "dog"; "doge"; "dogs"; "x"];
!count
