Correction

(* Question 1 *)

(* Les lettres d'un facteur (== sous-chaîne) de w doivent être consécutives dans w. *)
(* Les lettres d'une sous-séquence (== sous-mot) de w n'ont pas à l'être (« à lettre », huhu). *)

(* Question 2 *)

let khrass_mp c t =
	let m = string_length c and n = string_length t in
	let rec aux l i =
		if i = n - m + 1 then
			rev l
		else
			aux (if sub_string t i m = c then i::l else l) (i + 1)
	in aux [] 0
;;

khrass_mp "aba" "aabaaaba";;

(* Complexité : O(mn) *)

(* Question 3 *)

(* w a au plus |w| bords (où |·| est la longueur d'un mot) *)
(* On peut définir une relation d'ordre total sur les bords : a < b ssi a est bord de b *)
(* Une fois qu'ils sont totalement ordonnés b_1 > ? > b_n, on a : bêta(b_i) = b_{i + 1} pour tout i *)

(* Question 4 *)

let kmp s =
	let n = string_length s in
	let l = make_vect (n + 1) 0 in
	for i = 1 to n - 1 do
		let k = ref i in
		while s.[i] <> s.[l.(!k)] & !k > 0 do
			k := l.(!k)
		done;
		(* Quand on sort de la boucle, soit s.[i] = s.[l.(!k)], soit !k = 0 *)
		l.(i + 1) <- if s.[i] = s.[l.(!k)] then l.(!k) + 1 else 0
	done;
	l
;;

kmp "abababbaba";; (* 0 0 0 1 2 3 4 0 1 2 3 *)
kmp "abaabab";; (* 0 0 0 1 1 2 3 2 *)

(* Question 5 *)

let trouver_occurrences u v =
	let t = kmp (u ^ "#" ^ v) in
	let n = string_length u in
	let m = string_length v in
	let c = ref 0 in
	let rec cherche occurrences i =
		if i == 1 + n + m + 1 then 
			rev occurrences
		else
			cherche (if t.(i) = n then (i - 2 * n - 1)::occurrences else occurrences) (i + 1)
	in cherche [] (2 * n + 1);
;;

trouver_occurrences "aba" "aabaaaba";;

(* Question 6 *)

let facteur_carre s =
	let n = string_length s in
	let a_facteur_carre = ref false in
	for i = 0 to n - 1 do
		let t = kmp (sub_string s i (n - i)) in
		for j = 1 to n - i do
			if j mod 2 == 0 && t.(j) = j / 2 then
				a_facteur_carre := true
		done
	done;
	!a_facteur_carre
;;

facteur_carre "ab";;
facteur_carre "abab";;

(* Question 7 *)

let est_primitif s =
	let n = string_length s in
	let t = kmp s in
	t.(n) > 0 && n mod (n - t.(n)) = 0
;;

est_primitif "ab";;
est_primitif "aaa";;
est_primitif "abab";;

(* Question 8 *)

let miroir s =
	let t = ref "" in
	let n = string_length s in
	for i = n - 1 downto 0 do
		t := !t ^ string_of_char s.[i]
	done;
	!t
;;

let prefixes_palindromes s =
	let n = string_length s in
	let t = kmp (s ^ "#" ^ miroir s) in
	let rec aux l i =
		if i = 1 then
			l
		else
			aux (sub_string s 0 t.(i)::l) t.(i)
	in aux [] (2 * n + 1)
;;

prefixes_palindromes "aabaab";;

(* Question 9 *)

let conjugues u v =
	let w = v ^ v in
	let n = string_length u in
	let l = trouver_occurrences u w in
	if l = [] then false else
	let i = hd l in
	v = sub_string w 0 i ^ sub_string w (i + n) (n - i)
;;

conjugues "abab" "bbaa";;
conjugues "abab" "baba";;