Hint Rewrite flat_map_concat_map : list.
Opaque Start.

(* Specifications: *)
Lemma G1_inv x :
rewt G1 [Start] x -> exists A M, A <<= P /\ ((M = [Start] \/ (M = [#] /\ A <> [])) /\ x = (C1 A) ++ M ++ encoding A).
Lemma L1_inv P x :
L (f1 P) x -> exists A, A <> nil /\ A <<= P /\ (x = embed_string (C1 A) ++ # :: encoding A).
Lemma G1_char P A (H : A <<= P) :
rewt (f1 P) [Start] (embed_string (C1 A) ++ [Start] ++ encoding A).
Lemma L1_char P A (H : A <<= P) : A <> [] ->
L (f1 P) (embed_string (C1 A) ++ # :: flat_map enc (rev A)).
Lemma G2_inv P x :
rewt (f2 P) [Start] x -> exists A M, A <<= P /\ ((M = [Start] \/ (M = [Hash] /\ A <> [])) /\ x = embed_string (C2 A) ++ M ++ encoding A).
Lemma L2_inv P x :
L (f2 P) x -> exists A, A <> nil /\ A <<= P /\ (x = embed_string (C2 A) ++ # :: flat_map enc (rev A)).
Lemma G2_char P A (H : A <<= P) :
rewt (f2 P) [Start] (embed_string (C2 A) ++ [Start] ++ flat_map enc (rev A)).
Lemma L2_char P A (H : A <<= P) : A <> [] ->
L (f2 P) (embed_string (C2 A) ++ # :: flat_map enc (rev A)).
Lemma enc_inj A1 A2 :
encoding A1 = encoding A2 -> A1 = A2.
Lemma reduction P :
PCP P <-> inter_nonempty (f P).