Advertisement
Darooha

Solution to "Prefix-Suffix Queries"

Dec 3rd, 2020 (edited)
1,738
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 3.52 KB | None | 0 0
  1. open Printf
  2. open Scanf
  3.  
  4. let read_int _ = bscanf Scanning.stdin " %d " (fun x -> x)
  5. let read_str _ = bscanf Scanning.stdin " %s " (fun x -> x)  
  6. let read_str_pair _ = bscanf Scanning.stdin " %s %s " (fun x y -> (x,y))
  7. let () =
  8.   let n = read_int () in
  9.   let str = Array.init n read_str in
  10.   let q = read_int () in
  11.   let query = Array.init q read_str_pair in  
  12.  
  13.   let rev s =
  14.     let l = String.length s in
  15.     String.init l (fun i -> s.[l-1-i])
  16.   in
  17.  
  18.   let stx = Array.init n (fun i -> rev str.(i)) in
  19.  
  20.   let perm = Array.init n (fun i -> i) in
  21.   let perx = Array.copy perm in
  22.  
  23.   Array.sort (fun i j -> compare str.(i) str.(j)) perm;
  24.   Array.sort (fun i j -> compare stx.(i) stx.(j)) perx;
  25.  
  26.   let perxinv = Array.make n 0 in
  27.   for i=0 to n-1 do
  28.     perxinv.(perx.(i)) <- i
  29.   done;
  30.  
  31.   let match_range str perm s =
  32.   (* Returns None if s is a previx of none of the strings in str.
  33.      returns Some (i,j) if the range [i,j] all match.
  34.   *)
  35.     let get i = str.(perm.(i)) in
  36.     let l = String.length s in
  37.    
  38.     let compl a = (* compares a to s up to the length of s *)
  39.       let m = String.length a in
  40.       if m < l then compare a s else compare (String.sub a 0 l) s
  41.     in
  42.    
  43.     let rec bsearch0 lo hi =
  44.     (* know that compl str.(lo) = -1 and compl str.(hi) >= 0 *)
  45.       if hi = lo+1 then hi else
  46.     let m = (lo+hi)/2 in
  47.     if compl (get m) >= 0 then bsearch0 lo m else bsearch0 m hi
  48.     in
  49.     let rec bsearch1 lo hi =
  50.     (* know that compl str.(lo) = 0 and compl str.(hi) > 0 *)
  51.       if hi = lo+1 then lo else
  52.     let m = (lo+hi)/2 in
  53.     if compl (get m) > 0 then bsearch1 lo m else bsearch1 m hi
  54.     in
  55.  
  56.     let c0 = compl (get 0) in
  57.     if c0 > 0 then None
  58.     else if c0 = 0 then (
  59.       if compl (get (n-1)) = 0 then Some (0, n-1)
  60.       else Some (0, bsearch1 0 (n-1))
  61.     ) else (
  62.       if compl (get (n-1)) < 0 then None else
  63.     let lo = bsearch0 0 (n-1) in
  64.     if compl (get lo) > 0 then None
  65.     else if compl (get (n-1)) <= 0 then Some (lo, n-1)
  66.     else Some (lo, bsearch1 lo (n-1))
  67.     )
  68.   in
  69.  
  70.   (* Fenwick trees, adjusted to work from 0 to n-1 *)
  71.   let f = Array.make (n+1) 0 in
  72.  
  73.   let increment i x =
  74.     let rec loop i = if i <= n then (
  75.       f.(i) <- f.(i) + x;
  76.       loop (i + (i land (-i)))
  77.     ) in
  78.     loop (i+1)
  79.   in
  80.  
  81.   let sum_to_left i =
  82.     let rec loop i ac = if i = 0 then ac else
  83.     loop (i - (i land (-i))) (ac + f.(i))
  84.     in
  85.     loop (i+1) 0
  86.   in
  87.  
  88.   let range_sum i j =
  89.     let to_remove = if i <= 0 then 0 else sum_to_left (i-1) in
  90.     (sum_to_left j) - to_remove
  91.   in
  92.  
  93.   let answer = Array.make q 0 in
  94.   let start_events = Array.make n [] in
  95.   let end_events = Array.make n [] in
  96.   (* These event lists are lists of (query numbers,i,j)
  97.       that happen at that point in time *)
  98.  
  99.   for q1 = 0 to q-1 do
  100.     let (pre,suf) = query.(q1) in
  101.     match (match_range str perm pre, match_range stx perx (rev suf)) with
  102.       | (None, None) -> ()
  103.       | (None, Some (i,j)) | (Some (i,j), None) -> answer.(q1) <- j-i+1
  104.       | (Some (i,j), Some (i',j')) ->
  105.     answer.(q1) <- j-i+1 + j'-i'+1;
  106.     start_events.(i) <- (q1,i',j') :: start_events.(i);
  107.     end_events.(j) <- (q1,i',j') :: end_events.(j)
  108.   done;
  109.  
  110.   for x=0 to n-1 do
  111.     let y = perxinv.(perm.(x)) in
  112.     List.iter (fun (q1, i', j') ->
  113.       answer.(q1) <- answer.(q1) + (range_sum i' j')
  114.     ) start_events.(x);
  115.  
  116.     increment y 1;
  117.  
  118.     List.iter (fun (q1, i', j') ->
  119.       answer.(q1) <- answer.(q1) - (range_sum i' j')
  120.     ) end_events.(x);
  121.   done;
  122.  
  123.   for q1 = 0 to q-1 do
  124.     printf "%d\n" answer.(q1)
  125.   done
  126.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement