let kmp_table pat =
  let n = String.length pat in
  let t = Array.make n 0 in
  let k = ref 0 in
  for i = 1 to n - 1 do
    while !k > 0 && pat.[!k] <> pat.[i] do
      k := t.(!k - 1)
    done;
    if pat.[!k] = pat.[i] then k := !k + 1;
    t.(i) <- !k
  done;
  t

let kmp_search text pat =
  let m = String.length text in
  let n = String.length pat in
  if n = 0 then 0
  else begin
    let t = kmp_table pat in
    let count = ref 0 in
    let k = ref 0 in
    for i = 0 to m - 1 do
      while !k > 0 && pat.[!k] <> text.[i] do
        k := t.(!k - 1)
      done;
      if pat.[!k] = text.[i] then k := !k + 1;
      if !k = n then begin
        count := !count + 1;
        k := t.(n - 1)
      end
    done;
    !count
  end

;;

kmp_search "abababcabababcababcc" "abab"
