Imports
import Mathlib
32.1. The Naive String-Matching Algorithm
This section defines the string/text model used throughout Chapter 32:
string matching. A string is a list of elements drawn from an alphabet.
We define the basic operations — length, prefix, suffix, and the
corresponding predicates — that the finite-automaton and KMP constructions
rely on.
The definitions are parameterized over the element type α; for concrete
executability, instantiate α := Char or α := UInt8.
Key definitions
-
Text α: a string (alias for List α).
-
length: number of characters.
-
textPrefix t k: the first k characters of t.
-
suffix t k: the last k characters of t.
-
isPrefix p t: p is a prefix of t.
-
isSuffix p t: p is a suffix of t.
All operations are zero-indexed: the first character is at position 0,
and taking a prefix of length 0 yields the empty list.
namespace CLRSnamespace Chapter32
A text (string) is a list of elements from an alphabet. Use α := Char
for concrete text, or a generic α for abstract reasoning.
abbrev Text (α : Type) := List α
variable {α : Type}
abbrev length (t : Text α) : ℕ := t.length
The prefix of t of length k. If k exceeds the text length, the
result is the full text.
def textPrefix (t : Text α) (k : ℕ) : Text α :=
t.take k
The suffix of t of length k. If k exceeds the text length, the
result is the full text.
def suffix (t : Text α) (k : ℕ) : Text α :=
t.drop (t.length - k)
def isPrefix (p t : Text α) : Prop :=
∃ s, p ++ s = t
def isSuffix (p t : Text α) : Prop :=
∃ s, s ++ p = t
p is a proper prefix of t: a prefix that is strictly shorter than t.
def isProperPrefix (p t : Text α) : Prop :=
isPrefix p t ∧ p.length < t.length
p is a proper suffix of t: a suffix that is strictly shorter than t.
def isProperSuffix (p t : Text α) : Prop :=
isSuffix p t ∧ p.length < t.length
The empty text is a prefix of every text.
theorem isPrefix_empty (t : Text α) : isPrefix [] t :=
⟨t, by simp [This simp argument is unused:
isPrefix
Hint: Omit it from the simp argument list.
simp ̵[̵i̵s̵P̵r̵e̵f̵i̵x̵]̵
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`isPrefix]⟩
The empty text is a suffix of every text.
theorem isSuffix_empty (t : Text α) : isSuffix [] t :=
⟨t, by simp [This simp argument is unused:
isSuffix
Hint: Omit it from the simp argument list.
simp ̵[̵i̵s̵S̵u̵f̵f̵i̵x̵]̵
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`isSuffix]⟩
Every text is a prefix of itself.
theorem isPrefix_self (t : Text α) : isPrefix t t :=
⟨[], by simp [This simp argument is unused:
isPrefix
Hint: Omit it from the simp argument list.
simp ̵[̵i̵s̵P̵r̵e̵f̵i̵x̵]̵
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`isPrefix]⟩
Every text is a suffix of itself.
theorem isSuffix_self (t : Text α) : isSuffix t t :=
⟨[], by simp [This simp argument is unused:
isSuffix
Hint: Omit it from the simp argument list.
simp ̵[̵i̵s̵S̵u̵f̵f̵i̵x̵]̵
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`isSuffix]⟩
If p is a prefix of t, then p.length ≤ t.length.
theorem isPrefix_length_le (hp : isPrefix p t) : p.length ≤ t.length := by
rcases hp with ⟨s, h⟩
have := calc
t.length = (p ++ s).length := by rw [h]
_ = p.length + s.length := by simp
omega
If p is a suffix of t, then p.length ≤ t.length.
theorem isSuffix_length_le (hp : isSuffix p t) : p.length ≤ t.length := by
rcases hp with ⟨s, h⟩
have := calc
t.length = (s ++ p).length := by rw [h]
_ = s.length + p.length := by simp
omega
The prefix of length 0 is the empty list.
Taking the prefix of length equal to the text length returns the whole text.
The suffix of length 0 is the empty list.
Taking the suffix of length equal to the text length returns the whole text.
@[simp]
theorem suffix_length (t : Text α) : suffix t t.length = t := by
simp [suffix]
The empty text has no non-empty prefix.
theorem textPrefix_nil_of_length_eq_zero (t : Text α) (h : length t = 0) (k : ℕ) : textPrefix t k = [] := by
have : t = [] := by simpa [length] using h
subst this; simp [textPrefix]
The empty text has no non-empty suffix.
theorem suffix_nil_of_length_eq_zero (t : Text α) (h : length t = 0) (k : ℕ) : suffix t k = [] := by
have : t = [] := by simpa [length] using h
subst this; simp [suffix]
textPrefix is a prefix of the original text.
theorem isPrefix_textPrefix (t : Text α) (k : ℕ) : isPrefix (textPrefix t k) t := by
refine ⟨t.drop k, ?_⟩
simp [This simp argument is unused:
isPrefix
Hint: Omit it from the simp argument list.
simp [i̵s̵P̵r̵e̵f̵i̵x̵,̵ ̵textPrefix, List.take_append_drop]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`isPrefix, textPrefix, List.take_append_drop]
suffix is a suffix of the original text.
theorem isSuffix_suffix (t : Text α) (k : ℕ) : isSuffix (suffix t k) t := by
refine ⟨t.take (t.length - k), ?_⟩
simp [This simp argument is unused:
isSuffix
Hint: Omit it from the simp argument list.
simp [̵i̵s̵S̵u̵f̵f̵i̵x̵,̵ ̵s̵u̵f̵f̵i̵x̵,̵[̲s̲u̲f̲f̲i̲x̲,̲ List.take_append_drop, add_comm]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`isSuffix, suffix, List.take_append_drop, This simp argument is unused:
add_comm
Hint: Omit it from the simp argument list.
simp [isSuffix, suffix, List.take_append_drop,̵ ̵a̵d̵d̵_̵c̵o̵m̵m̵]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`add_comm]
end Chapter32end CLRS
Definitions and proofs
Section 32.1 — Naive String-Matching Algorithm
The naive string-matching algorithm (CLRS §32.1) finds all occurrences of a
pattern P of length m in a text T of length n by trying every possible
shift s = 0, 1, …, n-m and checking whether P matches T at that
position. The worst-case running time is Θ((n-m+1)·m) = O(m·n).
Key definitions
-
matchesAt T P s — pattern P occurs in text T starting at shift s.
-
naiveMatcher T P — returns the list of all shifts where P occurs in T.
-
noMatch — convenience abbreviation for the empty match list.
Notation
This file uses Text α = List α from Section_32_1_String_Model
and standard Nat-based lengths.
namespace CLRSnamespace Chapter32variable {α : Type} [BEq α] [DecidableEq α]
Pattern P matches text T at shift s: the substring of T from
position s of length |P| equals P. Formally,
(T.drop s).take |P| = P.
def matchesAt (T P : Text α) (s : ℕ) : Bool :=
if s + P.length ≤ T.length then
(T.drop s).take P.length == P
else
false
The naive string matcher: enumerate all shifts s ∈ [0, n-m] and
return those where the pattern matches.
def naiveMatcher (T P : Text α) : List ℕ :=
if P.length = 0 then
List.range (T.length + 1)
else
let n := T.length
let m := P.length
let maxShift := n - m
(List.range (maxShift + 1)).filter fun s => matchesAt T P s
Convenience abbreviation for "no match".
abbrev noMatch : List ℕ := []
If a shift s is in naiveMatcher T P, then matchesAt T P s is true.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_sound`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem naiveMatcher_sound (T P : Text α) (s : ℕ) (h : s ∈ naiveMatcher T P) :
matchesAt T P s := by
unfold naiveMatcher at h
split at h
·
rename_i hzero
have hempty : P = [] := by
cases P
· rfl
· simp at hzero
subst hempty
unfold matchesAt
have hs : s ≤ T.length := by
have := List.mem_range.mp h
omega
simp [hs]
·
have hmem := List.mem_filter.mp h
exact hmem.2
If matchesAt T P s is true, then s is in naiveMatcher T P.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_complete`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem naiveMatcher_complete (T P : Text α) (s : ℕ) (hmatch : matchesAt T P s) :
s ∈ naiveMatcher T P := by
unfold naiveMatcher
by_cases hzero : P.length = 0
·
have hempty : P = [] := by
cases P
· rfl
· simp at hzero
subst hempty
unfold matchesAt at hmatch
simp at hmatch
have hs : s < T.length + 1 := by omega
simp [hs]
·
have hbound : s + P.length ≤ T.length := by
unfold matchesAt at hmatch
split at hmatch
· assumption
· simp at hmatch
have hshift : s ≤ T.length - P.length := by
omega
have hle : s < (T.length - P.length) + 1 := by omega
have hmatch' : matchesAt T P s = true := hmatch
simpa [hzero] using
List.mem_filter.mpr ⟨List.mem_range.mpr hle, hmatch'⟩
The empty pattern matches at every position.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_empty`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_empty`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_empty`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
@[simp]
automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_empty`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem naiveMatcher_empty (T : Text α) : naiveMatcher T [] = List.range (T.length + 1) := by
unfold naiveMatcher; simp
If the pattern is longer than the text, there are no matches.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`Try `simp at h` instead of `simpa using h`
Note: This linter can be disabled with `set_option linter.unnecessarySimpa false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.naiveMatcher_pattern_too_long`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem naiveMatcher_pattern_too_long (T P : Text α) (h : T.length < P.length) :
naiveMatcher T P = noMatch := by
unfold naiveMatcher noMatch
by_cases hzero : P.length = 0
·
have : T.length < 0 := by Try `simp at h` instead of `simpa using h`
Note: This linter can be disabled with `set_option linter.unnecessarySimpa false`simpa [hzero] using h
omega
· have hsub : T.length - P.length = 0 := by omega
simp [hzero, hsub]
have hfalse : matchesAt T P 0 = false := by
unfold matchesAt
simp
omega
simp [hfalse]
Shifts returned by naiveMatcher are within bounds.
theorem naiveMatcher_shifts_valid (T P : Text α) (s : ℕ) (h : s ∈ naiveMatcher T P) :
s + P.length ≤ T.length := by
have hmatch := naiveMatcher_sound T P s h
unfold matchesAt at hmatch
split at hmatch
· assumption
· simp at hmatch
end Chapter32end CLRS
Imports
32.2. The Rabin–Karp Algorithm
The Rabin–Karp algorithm (CLRS §32.2) finds all occurrences of a pattern P
in a text T by hashing the pattern and every |P|-length window of T,
and comparing the hashes modulo q. A shift whose hash matches but whose
string does not is a spurious hit: the algorithm rules it out with an
explicit character-by-character comparison (matchesAt), so it remains
correct for every choice of modulus.
Key definitions
-
hash d q val w — the base-d modular hash of w over the numeric
values val c, computed by Horner's rule modulo q.
-
rabinKarpMatcher T P d q val — returns the list of all shifts where
P occurs in T (hash match plus explicit comparison), mirroring
naiveMatcher.
Main results
-
Theorem hash_snoc — the O(1) incremental update
hash (w ++ [c]) = (hash w · d + val c) mod q.
-
Theorem hash_eq_of_text_eq — equal strings have equal hashes; hence a
real match is never discarded as a spurious hit.
-
Theorem rabinKarp_sound — every shift returned by rabinKarpMatcher
is a valid match.
-
Theorem rabinKarp_complete — every valid match is returned by
rabinKarpMatcher.
-
Theorem rabinKarp_correct — rabinKarpMatcher agrees with
naiveMatcher on every shift.
The CLRS window-slide recurrence (eq. (32.3)) is proved as hash_slide.
rabinKarpRollingMatches_correct connects the rolling execution to the
all-occurrences specification, while rabinKarpRollingCost_eq and
rabinKarpRollingCost_le attach the deterministic work bound to that
execution.
Notation conventions used in this section:
-
T : the text being searched
-
P : the pattern being searched for
-
d : the radix of the numeric alphabet
-
q : the modulus (CLRS assumes 0 < q)
-
val : assigns each alphabet symbol a numeric value in ℕ
namespace CLRSnamespace Chapter32variable {α : Type} [BEq α] [DecidableEq α] [LawfulBEq α]
The base-d modular hash of w over the numeric values val c, computed by
Horner's rule modulo q (CLRS §32.2). For w = [a₀, …, a_{k-1}] this is
((⋯((val a₀ · d + val a₁) · d + …) · d + val a_{k-1}) mod q. The function
is total (x % 0 = x); CLRS assumes a modulus 0 < q.
def hash (d q : ℕ) (val : α → ℕ) (w : Text α) : ℕ :=
w.foldl (fun acc c => (acc * d + val c) % q) 0
The O(1) incremental update: appending a character to a string costs one
multiplication, one addition and one modulus, rather than a full re-hash.
This is the step used to seed the Rabin–Karp hashes (CLRS §32.2).
automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem hash_snoc (d q : ℕ) (val : α → ℕ) (w : Text α) (c : α) :
hash d q val (w ++ [c]) = (hash d q val w * d + val c) % q := by
unfold hash
rw [List.foldl_append]
simp
Equal strings have equal hashes, for any radix, modulus and value map.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_eq_of_text_eq`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_eq_of_text_eq`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_eq_of_text_eq`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_eq_of_text_eq`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem hash_eq_of_text_eq (d q : ℕ) (val : α → ℕ) {w₁ w₂ : Text α} (h : w₁ = w₂) :
hash d q val w₁ = hash d q val w₂ := by
subst h
rfl
If the pattern matches at shift s, then the window's hash equals the
pattern's hash: a real match is never discarded as a spurious hit. This is
the completeness half of the hash test.
lemma hash_beq_of_matchesAt (T P : Text α) (d q : ℕ) (val : α → ℕ) (s : ℕ)
(hm : matchesAt T P s = true) :
(hash d q val ((T.drop s).take P.length) == hash d q val P) = true := by
have hwind : ((T.drop s).take P.length == P) = true := by
unfold matchesAt at hm
split at hm
· simpa using hm
· contradiction
have hwindEq : (T.drop s).take P.length = P := by
exact beq_iff_eq.mp hwind
rw [hash_eq_of_text_eq d q val hwindEq]
simp
The Rabin–Karp acceptance test for shift s: the hash of the window
(T.drop s).take |P| equals the hash of P, and the window literally
equals P. The second conjunct filters out spurious hits, keeping the test
sound for every modulus.
def rabinKarpShift (T P : Text α) (d q : ℕ) (val : α → ℕ) (s : ℕ) : Bool :=
(hash d q val ((T.drop s).take P.length) == hash d q val P) && matchesAt T P s
The Rabin–Karp string matcher: enumerate all shifts and return those that
pass rabinKarpShift. For an empty pattern it returns every shift, exactly
like naiveMatcher.
def rabinKarpMatcher (T P : Text α) (d q : ℕ) (val : α → ℕ) : List ℕ :=
if P.length = 0 then
List.range (T.length + 1)
else
let n := T.length
let m := P.length
(List.range (n - m + 1)).filter (rabinKarpShift T P d q val)
The Rabin–Karp acceptance test agrees with the plain match test on every
shift: when the pattern matches, the hash equality is automatic, and when it
does not, the explicit comparison rejects the shift regardless of the hash.
If a shift s is in rabinKarpMatcher, then matchesAt T P s is true.
theorem rabinKarp_sound (T P : Text α) (d q : ℕ) (val : α → ℕ) (s : ℕ)
(h : s ∈ rabinKarpMatcher T P d q val) : matchesAt T P s := by
unfold rabinKarpMatcher at h
split at h
· rename_i hzero
have hempty : P = [] := by
cases P
· rfl
· simp at hzero
subst hempty
unfold matchesAt
have hs : s ≤ T.length := by
have := List.mem_range.mp h
omega
simp [hs]
· have hmem := List.mem_filter.mp h
simpa [rabinKarpShift_eq_matchesAt T P d q val s] using hmem.2
If matchesAt T P s is true, then s is in rabinKarpMatcher.
theorem rabinKarp_complete (T P : Text α) (d q : ℕ) (val : α → ℕ) (s : ℕ)
(hmatch : matchesAt T P s) : s ∈ rabinKarpMatcher T P d q val := by
unfold rabinKarpMatcher
by_cases hzero : P.length = 0
· have hempty : P = [] := by
cases P
· rfl
· simp at hzero
subst hempty
unfold matchesAt at hmatch
simp at hmatch
have hs : s < T.length + 1 := by omega
simp [hs]
· have hbound : s + P.length ≤ T.length := by
unfold matchesAt at hmatch
split at hmatch
· assumption
· simp at hmatch
have hle : s < (T.length - P.length) + 1 := by omega
have hmatch' : matchesAt T P s = true := hmatch
have hshift : rabinKarpShift T P d q val s = true := by
rw [rabinKarpShift_eq_matchesAt T P d q val s, hmatch']
simpa [hzero] using
List.mem_filter.mpr ⟨List.mem_range.mpr hle, hshift⟩
Correctness of Rabin–Karp. rabinKarpMatcher returns exactly the shifts
that naiveMatcher returns, for every text, pattern, radix, modulus and
numeric value map. Soundness is by construction (the explicit comparison);
completeness uses the fact that equal strings have equal hashes, so a valid
match can never be filtered out as a spurious hit.
section Rollingvariable {α : Type} [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α]
Horner evaluation of w over val without the intermediate modular
reductions. hash d q val w is exactly hashNoMod d val w % q.
def hashNoMod (d : ℕ) (val : α → ℕ) (w : Text α) : ℕ :=
w.foldl (fun acc c => acc * d + val c) 0
A Horner fold is congruent modulo q when its initial accumulator is.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_mod_congr`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_mod_congr`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_mod_congr`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_mod_congr`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_mod_congr`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_mod_congr`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_mod_congr`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma foldl_horner_mod_congr (d q : ℕ) (val : α → ℕ) (as : Text α) {x y : ℕ}
(h : Nat.ModEq q x y) :
Nat.ModEq q (as.foldl (fun a c => a * d + val c) x)
(as.foldl (fun a c => a * d + val c) y) := by
induction as generalizing x y with
| nil => simpa using h
| cons a as ih =>
have hstep : Nat.ModEq q (x * d + val a) (y * d + val a) :=
(Nat.ModEq.mul h (Nat.ModEq.refl d)).add (Nat.ModEq.refl (val a))
exact ih hstep
Reducing after each Horner step is congruent to reducing once at the end.
lemma foldl_mod_congr (d q : ℕ) (val : α → ℕ) (w : Text α) (acc : ℕ) :
Nat.ModEq q (w.foldl (fun a c => (a * d + val c) % q) acc)
(w.foldl (fun a c => a * d + val c) acc) := by
induction w generalizing acc with
| nil => exact Nat.ModEq.refl acc
| cons a as ih =>
rw [List.foldl_cons, List.foldl_cons]
have h1 := ih ((acc * d + val a) % q)
have h2 : Nat.ModEq q (as.foldl (fun a c => a * d + val c) ((acc * d + val a) % q))
(as.foldl (fun a c => a * d + val c) (acc * d + val a)) :=
foldl_horner_mod_congr d q val as (Nat.mod_modEq (acc * d + val a) q)
exact h1.trans h2
hash is always below the modulus for a positive modulus.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_lt`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_lt`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_lt`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_lt`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_lt`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_lt`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_lt`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_lt`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_lt`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_lt`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_lt`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_lt`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_lt`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_lt`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem hash_lt (d q : ℕ) (val : α → ℕ) (w : Text α) (hq : 0 < q) :
hash d q val w < q := by
unfold hash
have hmain : ∀ acc, acc < q →
(w.foldl (fun a c => (a * d + val c) % q) acc) < q := by
induction w with
| nil => intro acc hacc; exact hacc
| cons a as ih =>
intro acc hacc
rw [List.foldl_cons]
exact ih ((acc * d + val a) % q) (Nat.mod_lt _ hq)
exact hmain 0 hq
hash is the Horner evaluation reduced modulo q.
theorem hash_eq_hashNoMod_mod (d q : ℕ) (val : α → ℕ) (w : Text α) :
hash d q val w = hashNoMod d val w % q := by
unfold hash hashNoMod
by_cases hq : q = 0
· subst q; simp
· have hqpos : 0 < q := Nat.pos_of_ne_zero hq
have hcong := foldl_mod_congr d q val w 0
have hl : (w.foldl (fun a c => (a * d + val c) % q) 0) < q := by
simpa [hash] using hash_lt d q val w hqpos
simpa [Nat.ModEq, Nat.mod_eq_of_lt hl] using hcong
A Horner fold with initial accumulator acc equals acc · d^|as| plus the
fold starting from 0.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_acc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_acc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_acc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_acc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_acc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_acc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_acc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_acc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_acc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_acc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_acc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_acc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_acc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_acc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.foldl_horner_acc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma foldl_horner_acc (d : ℕ) (val : α → ℕ) (as : Text α) (acc : ℕ) :
as.foldl (fun a c => a * d + val c) acc
= acc * d ^ as.length + as.foldl (fun a c => a * d + val c) 0 := by
induction as generalizing acc with
| nil => simp
| cons b bs ih =>
rw [List.foldl_cons, ih (acc * d + val b)]
rw [List.foldl_cons, ih (0 * d + val b)]
rw [List.length_cons, pow_succ]
ring
The leading character contributes val a · d^|as| to the Horner hash.
(x + y) % q is unchanged when y is reduced modulo q.
lemma add_mod_add_mod (q x y : ℕ) : (x + y) % q = (x + y % q) % q :=
(Nat.ModEq.add (Nat.ModEq.refl x) (Nat.mod_modEq y q)).symm
The leading character's contribution to the Horner hash (CLRS §32.2).
Casting x % q into ZMod q is the same as casting x.
lemma zmod_natCast_mod (q x : ℕ) : ((x % q : ℕ) : ZMod q) = (x : ZMod q) :=
(ZMod.natCast_eq_natCast_iff (x % q) x q).2 (Nat.mod_mod x q)
The rolling recurrence (CLRS eq. (32.3)): given the hash h of a nonempty
window w and the incoming character c, the hash of w.drop 1 ++ [c] is
(d·h + val c − val w[0]·d^|w|) mod q, with the subtraction normalized into
ℕ by the + q term (valid for 0 < q).
def slideHash (d q : ℕ) (val : α → ℕ) (h : ℕ) (w : Text α) (c : α) : ℕ :=
(d * h + val c + q - (val (w.headD default) * d ^ w.length) % q) % q
The ZMod q value of a slide: the + q − x normalization collapses to the
true modular subtraction.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.slideHash_zmod`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma slideHash_zmod (d q : ℕ) (hq : 0 < q) (val : α → ℕ) (w : Text α) (h : ℕ) (c : α) :
((slideHash d q val h w c : ℕ) : ZMod q)
= (d : ZMod q) * (h : ZMod q) + (val c : ZMod q)
- (val (w.headD default) : ZMod q) * (d : ZMod q) ^ w.length := by
unfold slideHash
rw [zmod_natCast_mod q (d * h + val c + q - (val (w.headD default) * d ^ w.length) % q)]
have hge : (val (w.headD default) * d ^ w.length) % q ≤ d * h + val c + q := by
exact Nat.le_trans (Nat.le_of_lt (Nat.mod_lt _ hq)) (Nat.le_add_left _ _)
rw [Nat.cast_sub hge]
rw [zmod_natCast_mod q (val (w.headD default) * d ^ w.length)]
push_cast
rw [ZMod.natCast_self]
ring
The Horner hash of a cons in ZMod q.
lemma hash_cons_zmod (d q : ℕ) (val : α → ℕ) (a : α) (as : Text α) :
(hash d q val (a :: as) : ZMod q)
= (val a : ZMod q) * (d : ZMod q) ^ as.length + (hash d q val as : ZMod q) := by
rw [hash_cons, zmod_natCast_mod]
push_cast
rfl
The Horner hash of a snoc in ZMod q.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_snoc_zmod`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_snoc_zmod`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_snoc_zmod`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_snoc_zmod`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_snoc_zmod`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_snoc_zmod`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.hash_snoc_zmod`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma hash_snoc_zmod (d q : ℕ) (val : α → ℕ) (w : Text α) (c : α) :
(hash d q val (w ++ [c]) : ZMod q)
= (hash d q val w : ZMod q) * d + (val c : ZMod q) := by
rw [hash_snoc, zmod_natCast_mod]
push_cast
rfl
Rabin–Karp rolling recurrence (CLRS eq. (32.3)). Sliding a nonempty window
by one position — dropping the leading character and appending a new one —
satisfies the hash recurrence below. The legacy slideHash recomputes
d ^ w.length, so this definition does not itself give a constant-cost
slide. The CachedPower companion prepares the power once and uses seven
fixed scalar arithmetic operations per update.
theorem hash_slide (d q : ℕ) (val : α → ℕ) (w : Text α) (c : α) (hq : 0 < q)
(hw : w ≠ []) :
hash d q val (w.drop 1 ++ [c]) = slideHash d q val (hash d q val w) w c := by
rcases w with _ | ⟨a, as⟩
· contradiction
change hash d q val (as ++ [c]) = slideHash d q val (hash d q val (a :: as)) (a :: as) c
have hl : hash d q val (as ++ [c]) < q := hash_lt d q val (as ++ [c]) hq
have hr : slideHash d q val (hash d q val (a :: as)) (a :: as) c < q := by
unfold slideHash; exact Nat.mod_lt _ hq
have hcong : ((hash d q val (as ++ [c]) : ZMod q)
= (slideHash d q val (hash d q val (a :: as)) (a :: as) c : ZMod q)) := by
rw [hash_snoc_zmod]
rw [slideHash_zmod d q hq val (a :: as) (hash d q val (a :: as)) c]
rw [hash_cons_zmod]
rw [List.length_cons, pow_succ]
simp only [List.headD]
ring
have hmod : hash d q val (as ++ [c]) % q = slideHash d q val (hash d q val (a :: as)) (a :: as) c % q :=
(ZMod.natCast_eq_natCast_iff _ _ q).1 hcong
rw [Nat.mod_eq_of_lt hl, Nat.mod_eq_of_lt hr] at hmod
exact hmod
range (n+1) mapped by f is f 0 followed by the shifted tail.
'change (List.range (n + 1 + 1)).map f = f 0 :: (List.range (n + 1)).map (fun i => f (i + 1))' tactic does nothing
Note: This linter can be disabled with `set_option linter.unusedTactic false`
lemma range_succ_map (n : ℕ) (f : ℕ → β) :
(List.range (n + 1)).map f = f 0 :: (List.range n).map (fun i => f (i + 1)) := by
induction n with
| zero => rfl
| succ n ih =>
'change (List.range (n + 1 + 1)).map f = f 0 :: (List.range (n + 1)).map (fun i => f (i + 1))' tactic does nothing
Note: This linter can be disabled with `set_option linter.unusedTactic false`change (List.range (n + 1 + 1)).map f = f 0 :: (List.range (n + 1)).map (fun i => f (i + 1))
rw [List.range_succ, List.map_append, List.map_cons, ih]
rw [List.range_succ, List.map_append, List.map_cons]
simp
The acceptance test of the rolling scan agrees with the plain match test.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingTest_eq_matchesAt`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingTest_eq_matchesAt`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingTest_eq_matchesAt`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingTest_eq_matchesAt`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingTest_eq_matchesAt`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingTest_eq_matchesAt`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingTest_eq_matchesAt`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingTest_eq_matchesAt`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingTest_eq_matchesAt`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingTest_eq_matchesAt`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingTest_eq_matchesAt`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingTest_eq_matchesAt`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingTest_eq_matchesAt`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingTest_eq_matchesAt`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma rollingTest_eq_matchesAt (T P : Text α) (d q : ℕ) (val : α → ℕ) (p m s : ℕ)
(w : Text α) (h : ℕ) (hp : p = hash d q val P) (hm : m = P.length)
(hw : w = (T.drop s).take m) (hh : h = hash d q val w) :
(h == p && matchesAt T P s) = matchesAt T P s := by
by_cases hmt : matchesAt T P s = true
· have hbeq : (h == p) = true := by
have hb := hash_beq_of_matchesAt T P d q val s hmt
simpa [hh, hp, hm, hw] using hb
simp [hmt, hbeq]
· have hf : matchesAt T P s = false := by
cases hb : matchesAt T P s <;> simp [hb] at hmt ⊢
simp [hf]
The hash-hit test of the rolling scan is exactly the window hash equality.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingHashHit_eq`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingHashHit_eq`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingHashHit_eq`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma rollingHashHit_eq (T P : Text α) (d q : ℕ) (val : α → ℕ) (p m s : ℕ)
(w : Text α) (h : ℕ) (hp : p = hash d q val P) (hm : m = P.length)
(hw : w = (T.drop s).take m) (hh : h = hash d q val w) :
(h == p) = (hash d q val ((T.drop s).take P.length) == hash d q val P) := by
simp [hh, hp, hm, hw]
The number of hash hits among the k+1 consecutive windows starting at
shift s, defined recursively so the head-split is definitional.
def hashHitsIn (T P : Text α) (d q : ℕ) (val : α → ℕ) (s k : ℕ) : ℕ :=
match k with
| 0 => if hash d q val ((T.drop s).take P.length) == hash d q val P then 1 else 0
| k + 1 => (if hash d q val ((T.drop s).take P.length) == hash d q val P then 1 else 0)
+ hashHitsIn T P d q val (s + 1) k
hashHitsIn over a single window.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.hashHitsIn_zero`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma hashHitsIn_zero (T P : Text α) (d q : ℕ) (val : α → ℕ) (s : ℕ) :
hashHitsIn T P d q val s 0
= (if hash d q val ((T.drop s).take P.length) == hash d q val P then 1 else 0) := rfl
hashHitsIn splits across the first window.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.hashHitsIn_succ`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.hashHitsIn_succ`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.hashHitsIn_succ`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma hashHitsIn_succ (T P : Text α) (d q : ℕ) (val : α → ℕ) (s k : ℕ) :
hashHitsIn T P d q val s (k + 1) = hashHitsIn T P d q val s 0 + hashHitsIn T P d q val (s + 1) k := by
rfl
Sliding the window: dropping one leading character and appending c yields
the next length-m window of T.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.window_slide`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma window_slide {T : Text α} {s m : ℕ} {w : Text α} {c : α} {rest' : Text α}
(hw : w = (T.drop s).take m) (hwlen : w.length = m) (hm0 : 0 < m)
(hr : c :: rest' = T.drop (s + m)) :
w.tail ++ [c] = (T.drop (s + 1)).take m := by
have hwrest : w ++ (c :: rest') = T.drop s := by
calc
w ++ (c :: rest') = (T.drop s).take m ++ T.drop (s + m) := by rw [hw, ← hr]
_ = (T.drop s).take m ++ (T.drop s).drop m := by rw [List.drop_drop]
_ = T.drop s := List.take_append_drop m (T.drop s)
have hlen_tail : w.tail.length = m - 1 := by
rw [List.length_tail, hwlen]
calc
w.tail ++ [c] = (w.tail ++ (c :: rest')).take m := by
rw [List.take_append]
have hle : w.tail.length ≤ m := by omega
have hone : m - w.tail.length = 1 := by omega
rw [List.take_of_length_le hle, hone]
simp
_ = ((w ++ (c :: rest')).drop 1).take m := by
rw [List.drop_append_of_le_length (show 1 ≤ w.length by omega)]
rw [List.drop_one]
_ = ((T.drop s).drop 1).take m := by rw [hwrest]
_ = (T.drop (s + 1)).take m := by
rw [List.drop_drop]
One rolling scan step, returning the matches found and the accumulated work.
def rollingGo (T P : Text α) (d q : ℕ) (val : α → ℕ) (p m s : ℕ) (w : Text α) (h : ℕ)
(rest : Text α) : List ℕ × ℕ :=
match rest with
| [] => (if h == p && matchesAt T P s then [s] else [], 1 + (if h == p then m else 0))
| c :: rest' =>
let (tail, costTail) := rollingGo T P d q val p m (s + 1) (w.tail ++ [c])
(slideHash d q val h w c) rest'
let conf := if h == p then m else 0
if h == p && matchesAt T P s then (s :: tail, conf + 1 + costTail)
else (tail, conf + 1 + costTail)
The rolling scan's specification: rollingGo returns exactly the shifts in
[s, s + rest.length] where P matches, and a cost of one rolling update per
shift plus an m-step character confirmation at every hash hit.
lemma rollingGo_spec (T P : Text α) (d q : ℕ) (val : α → ℕ) (p m s : ℕ) (w : Text α) (h : ℕ)
(rest : Text α) (hq : 0 < q) (hm0 : 0 < m) (hp : p = hash d q val P) (hm : m = P.length)
(hw : w = (T.drop s).take m) (hwlen : w.length = m) (hh : h = hash d q val w)
(hr : rest = T.drop (s + m)) :
rollingGo T P d q val p m s w h rest =
( ((List.range (rest.length + 1)).map (fun i => s + i)).filter (fun s' => matchesAt T P s'),
rest.length + 1 + hashHitsIn T P d q val s rest.length * m ) := by
induction rest generalizing s w h with
| nil =>
rw [rollingGo]
rw [rollingTest_eq_matchesAt T P d q val p m s w h hp hm hw hh]
rw [rollingHashHit_eq T P d q val p m s w h hp hm hw hh]
simp only [List.length_nil]
rw [hashHitsIn_zero T P d q val s]
congr
· by_cases h : matchesAt T P s <;> simp [h]
· by_cases h : hash d q val ((T.drop s).take P.length) == hash d q val P <;> simp [h]
| cons c rest' ih =>
simp only [rollingGo]
have hw' : w.tail ++ [c] = (T.drop (s + 1)).take m := window_slide hw hwlen hm0 hr
have hwlen' : (w.tail ++ [c]).length = m := by
rw [List.length_append, List.length_cons, List.length_nil]
rw [List.length_tail, hwlen]
omega
have hh' : slideHash d q val h w c = hash d q val (w.tail ++ [c]) := by
have hwne : w ≠ [] := by
intro he; subst he; simp at hwlen; omega
rw [hh]
simpa [List.drop_one] using (hash_slide d q val w c hq hwne).symm
have hr' : rest' = T.drop ((s + 1) + m) := by
calc
rest' = (c :: rest').drop 1 := by rfl
_ = (T.drop (s + m)).drop 1 := by rw [hr]
_ = T.drop ((s + 1) + m) := by rw [List.drop_drop]; congr 1; omega
simp only [ih (s + 1) (w.tail ++ [c]) (slideHash d q val h w c) hw' hwlen' hh' hr']
rw [rollingTest_eq_matchesAt T P d q val p m s w h hp hm hw hh]
rw [rollingHashHit_eq T P d q val p m s w h hp hm hw hh]
simp only [List.length_cons]
rw [range_succ_map (rest'.length + 1) (fun i => s + i)]
rw [hashHitsIn_succ T P d q val s rest'.length]
have hmap : ((List.range (rest'.length + 1)).map (fun i => s + 1 + i)) =
((List.range (rest'.length + 1)).map (fun i => s + (i + 1))) := by
congr; funext i; omega
have hcost : (if hash d q val ((T.drop s).take P.length) == hash d q val P then m else 0)
= hashHitsIn T P d q val s 0 * m := by
simp only [hashHitsIn]
cases hb : hash d q val ((T.drop s).take P.length) == hash d q val P <;> simp
rw [hmap, hcost]
apply Prod.ext
· simp only [List.filter_cons, This simp argument is unused:
List.map_cons
Hint: Omit it from the simp argument list.
simp only [List.filter_cons, L̵i̵s̵t̵.̵m̵a̵p̵_̵c̵o̵n̵s̵,̵ ̵List.map_append]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`List.map_cons, This simp argument is unused:
List.map_append
Hint: Omit it from the simp argument list.
simp only [List.filter_cons, List.map_cons,̵ ̵L̵i̵s̵t̵.̵m̵a̵p̵_̵a̵p̵p̵e̵n̵d̵]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`List.map_append]
by_cases h : matchesAt T P s <;> simp [h]
· by_cases h : matchesAt T P s <;> simp [h] <;> ring
The rolling Rabin-Karp matcher (CLRS §32.2), returning the list of matches
and the deterministic work performed.
def rabinKarpRolling (T P : Text α) (d q : ℕ) (val : α → ℕ) : List ℕ × ℕ :=
let m := P.length
let p := hash d q val P
if m = 0 then (List.range (T.length + 1), T.length + 1)
else
let r := rollingGo T P d q val p m 0 (T.take m) (hash d q val (T.take m)) (T.drop m)
(r.1, m + r.2)
The matches returned by the rolling matcher.
def rabinKarpRollingMatches (T P : Text α) (d q : ℕ) (val : α → ℕ) : List ℕ :=
(rabinKarpRolling T P d q val).1
Selected shift/confirmation budget: a legacy m seed charge, one
charge per shift and m per hash hit. It does not count power preparation,
all seed arithmetic or list-window movement; the cached-power companion adds
actual power and both seed-hash counters.
def rabinKarpRollingCost (T P : Text α) (d q : ℕ) (val : α → ℕ) : ℕ :=
(rabinKarpRolling T P d q val).2
The top-level rolling scan applied to the whole text.
lemma rollingGo_top (T P : Text α) (d q : ℕ) (val : α → ℕ) (hq : 0 < q) (hm0 : 0 < P.length)
(hmle : P.length ≤ T.length) :
rollingGo T P d q val (hash d q val P) P.length 0 (T.take P.length)
(hash d q val (T.take P.length)) (T.drop P.length) =
(((List.range (T.length - P.length + 1)).filter (fun s' => matchesAt T P s')),
T.length - P.length + 1 + hashHitsIn T P d q val 0 (T.length - P.length) * P.length) := by
have hwlen : (T.take P.length).length = P.length := by rw [List.length_take]; omega
have hspec := rollingGo_spec T P d q val (hash d q val P) P.length 0 (T.take P.length)
(hash d q val (T.take P.length)) (T.drop P.length) hq hm0 rfl rfl rfl hwlen rfl (by simp)
rw [hspec]
simp [List.length_drop]
Correctness of the rolling Rabin-Karp matcher. The rolling matcher returns
exactly the shifts returned by naiveMatcher (and hence by the hash-and-confirm
rabinKarpMatcher): rolling hashes preserve exactly the set of matches.
The separate cached-power implementation supplies a fixed-operation slide.
theorem rabinKarpRollingMatches_correct (T P : Text α) (d q : ℕ) (val : α → ℕ) (hq : 0 < q) :
rabinKarpRollingMatches T P d q val = naiveMatcher T P := by
by_cases hzero : P.length = 0
· simp [rabinKarpRollingMatches, rabinKarpRolling, hzero, naiveMatcher]
· have hm0 : 0 < P.length := Nat.pos_of_ne_zero hzero
by_cases hlong : T.length < P.length
· have hdrop : T.drop P.length = [] := by
apply List.eq_nil_of_length_eq_zero; rw [List.length_drop]; omega
have hmt : matchesAt T P 0 = false := by unfold matchesAt; simp [hlong]
rw [show rabinKarpRollingMatches T P d q val = [] by
simp [rabinKarpRollingMatches, rabinKarpRolling, hzero, This simp argument is unused:
hlong
Hint: Omit it from the simp argument list.
simp [rabinKarpRollingMatches, rabinKarpRolling, hzero, h̵l̵o̵n̵g̵,̵ ̵rollingGo, hdrop, hmt]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`hlong, rollingGo, hdrop, hmt]]
simpa [noMatch] using (naiveMatcher_pattern_too_long T P hlong).symm
· have hmle : P.length ≤ T.length := Nat.le_of_not_gt hlong
have htop := rollingGo_top T P d q val hq hm0 hmle
simp [rabinKarpRollingMatches, rabinKarpRolling, hzero, This simp argument is unused:
hlong
Hint: Omit it from the simp argument list.
simp [rabinKarpRollingMatches, rabinKarpRolling, hzero, hl̵o̵n̵g̵,̵ ̵h̵top, naiveMatcher]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`hlong, htop, naiveMatcher]
The refined work bound: the rolling matcher performs exactly m operations to
seed the first hash, one rolling update per shift, and an m-step character
confirmation at every hash hit — the term that is O(n + m·(#hits)). A
spurious hit is a hash hit that is not a real match; both cost the same m
confirmations.
Used `tac1 <;> tac2` where `(tac1; tac2)` would suffice
Note: This linter can be disabled with `set_option linter.unnecessarySeqFocus false`
theorem rabinKarpRollingCost_eq (T P : Text α) (d q : ℕ) (val : α → ℕ) (hq : 0 < q) :
rabinKarpRollingCost T P d q val
= P.length + (T.length - P.length + 1) + hashHitsIn T P d q val 0 (T.length - P.length) * P.length := by
by_cases hzero : P.length = 0
· simp [rabinKarpRollingCost, rabinKarpRolling, hzero]
· have hm0 : 0 < P.length := Nat.pos_of_ne_zero hzero
by_cases hlong : T.length < P.length
· have hdrop : T.drop P.length = [] := by
apply List.eq_nil_of_length_eq_zero; rw [List.length_drop]; omega
have hsub : T.length - P.length = 0 := by omega
simp [rabinKarpRollingCost, rabinKarpRolling, hzero, This simp argument is unused:
hlong
Hint: Omit it from the simp argument list.
simp [rabinKarpRollingCost, rabinKarpRolling, hzero, h̵l̵o̵n̵g̵,̵ ̵rollingGo, hdrop, hashHitsIn, hsub]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`hlong, rollingGo, hdrop, hashHitsIn, hsub]
by_cases hhit : hash d q val (T.take P.length) = hash d q val P <;> simp [hhit] Used `tac1 <;> tac2` where `(tac1; tac2)` would suffice
Note: This linter can be disabled with `set_option linter.unnecessarySeqFocus false`<;> omega
· have hmle : P.length ≤ T.length := Nat.le_of_not_gt hlong
have htop := rollingGo_top T P d q val hq hm0 hmle
simp [rabinKarpRollingCost, rabinKarpRolling, hzero, This simp argument is unused:
hlong
Hint: Omit it from the simp argument list.
simp [rabinKarpRollingCost, rabinKarpRolling, hzero, hl̵o̵n̵g̵,̵ ̵h̵top]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`hlong, htop]
omega
The cost-only trace of the rolling scan, mirroring rollingGo's second
component without the match-list bookkeeping.
def rollingCost (T P : Text α) (d q : ℕ) (val : α → ℕ) (p m s : ℕ) (w : Text α) (h : ℕ)
(rest : Text α) : ℕ :=
match rest with
| [] => 1 + (if h == p then m else 0)
| c :: rest' => (if h == p then m else 0) + 1 + rollingCost T P d q val p m (s + 1) (w.tail ++ [c])
(slideHash d q val h w c) rest'
rollingGo's cost component is exactly rollingCost.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingGo_snd_eq_rollingCost`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingGo_snd_eq_rollingCost`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingGo_snd_eq_rollingCost`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingGo_snd_eq_rollingCost`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingGo_snd_eq_rollingCost`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingGo_snd_eq_rollingCost`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingGo_snd_eq_rollingCost`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingGo_snd_eq_rollingCost`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingGo_snd_eq_rollingCost`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingGo_snd_eq_rollingCost`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma rollingGo_snd_eq_rollingCost (T P : Text α) (d q : ℕ) (val : α → ℕ) (p m s : ℕ) (w : Text α)
(h : ℕ) (rest : Text α) :
(rollingGo T P d q val p m s w h rest).2 = rollingCost T P d q val p m s w h rest := by
induction rest generalizing s w h with
| nil => rfl
| cons c rest' ih =>
simp only [rollingGo, rollingCost]
cases hb : (h == p && matchesAt T P s) <;> simp [This simp argument is unused:
hb
Hint: Omit it from the simp argument list.
simp [h̵b̵,̵ ̵ih]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`hb, ih]
Each step of the rolling scan costs at most m + 1 operations: one rolling
update plus at most m confirmation comparisons.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.rollingCost_le`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma rollingCost_le (T P : Text α) (d q : ℕ) (val : α → ℕ) (p m s : ℕ) (w : Text α) (h : ℕ)
(rest : Text α) :
rollingCost T P d q val p m s w h rest ≤ (rest.length + 1) * (m + 1) := by
induction rest generalizing s w h with
| nil =>
simp [rollingCost]
have hif : (if h = p then m else 0) ≤ m := by by_cases hh : h = p <;> simp [hh] <;> this tactic is never executed
Note: This linter can be disabled with `set_option linter.unreachableTactic false`'omega' tactic does nothing
Note: This linter can be disabled with `set_option linter.unusedTactic false`omega
omega
| cons c rest' ih =>
simp [rollingCost]
have hih := ih (s + 1) (w.tail ++ [c]) (slideHash d q val h w c)
have hif : (if h = p then m else 0) ≤ m := by by_cases hh : h = p <;> simp [hh] <;> 'omega' tactic does nothing
Note: This linter can be disabled with `set_option linter.unusedTactic false`this tactic is never executed
Note: This linter can be disabled with `set_option linter.unreachableTactic false`omega
nlinarith [hif, hih]
rollingGo's cost component is bounded by (rest.length + 1) * (m + 1).
The worst-case deterministic work bound: the rolling matcher never performs
more than m + (n − m + 1)·(m + 1) operations — O(n·m) in the worst case,
matching the textbook statement (CLRS §32.2). When hits are sparse, the
refined rabinKarpRollingCost_eq gives the expected O(n + m·(#hits)) form.
Used `tac1 <;> tac2` where `(tac1; tac2)` would suffice
Note: This linter can be disabled with `set_option linter.unnecessarySeqFocus false`
theorem rabinKarpRollingCost_le (T P : Text α) (d q : ℕ) (val : α → ℕ) :
rabinKarpRollingCost T P d q val ≤ P.length + (T.length - P.length + 1) * (P.length + 1) := by
by_cases hzero : P.length = 0
· simp [rabinKarpRollingCost, rabinKarpRolling, hzero]
· have hm0 : 0 < P.length := Nat.pos_of_ne_zero hzero
by_cases hlong : T.length < P.length
· have hdrop : T.drop P.length = [] := by
apply List.eq_nil_of_length_eq_zero; rw [List.length_drop]; omega
have hsub : T.length - P.length = 0 := by omega
simp [rabinKarpRollingCost, rabinKarpRolling, hzero, This simp argument is unused:
hlong
Hint: Omit it from the simp argument list.
simp [rabinKarpRollingCost, rabinKarpRolling, hzero, h̵l̵o̵n̵g̵,̵ ̵rollingGo, hdrop, hsub]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`hlong, rollingGo, hdrop, hsub]
by_cases hhit : hash d q val (T.take P.length) = hash d q val P <;> simp [hhit] Used `tac1 <;> tac2` where `(tac1; tac2)` would suffice
Note: This linter can be disabled with `set_option linter.unnecessarySeqFocus false`<;> omega
· have hmle : P.length ≤ T.length := Nat.le_of_not_gt hlong
have hbound : (rollingGo T P d q val (hash d q val P) P.length 0 (T.take P.length)
(hash d q val (T.take P.length)) (T.drop P.length)).2
≤ (T.length - P.length + 1) * (P.length + 1) := by
simpa [List.length_drop] using
(rollingGo_cost_le T P d q val (hash d q val P) P.length 0 (T.take P.length)
(hash d q val (T.take P.length)) (T.drop P.length))
simp [rabinKarpRollingCost, rabinKarpRolling, hzero, This simp argument is unused:
hlong
Hint: Omit it from the simp argument list.
simp [rabinKarpRollingCost, rabinKarpRolling, hzero,̵ ̵h̵l̵o̵n̵g̵]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`hlong]
omega
end Rollingend Chapter32end CLRS
Definitions and proofs
Rabin–Karp with a prepared high-position power
Prepare the power once and pass it through every slide. The fixed slide formula
contains no exponentiation or window-length traversal. Power and seed hashing
are counted from their actual recursions. The scan retains the existing
shift/confirmation budget; list window movement, symbol-map evaluation and
bit-operation costs are outside this scalar charge model.
namespace CLRS.Chapter32.RKExecutionvariable {α : Type} [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α]def power (d : Nat) : Nat → Nat × Nat
| 0 => (1,0)
| m+1 => let prev := power d m; (prev.1*d,prev.2+1)@[simp] theorem power_value (d m : Nat) : (power d m).1 = d^m := by
induction m with
| zero => rfl
| succ m ih => simp [power, ih, pow_succ]@[simp] theorem power_multiplications (d m : Nat) : (power d m).2 = m := by
induction m with
| zero => rfl
| succ m ih => simp [power, ih]def hashLoop (d q : Nat) (val : α → Nat) : Nat → Text α → Nat × Nat
| acc, [] => (acc,0)
| acc, c::xs =>
let rest := hashLoop d q val ((acc*d+val c)%q) xs
(rest.1,rest.2+1)automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.hashLoop_value`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.hashLoop_value`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.hashLoop_value`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.hashLoop_value`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.hashLoop_value`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
@[simp] automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.hashLoop_value`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem hashLoop_value (d q : Nat) (val : α → Nat) (acc : Nat) (xs : Text α) :
(hashLoop d q val acc xs).1 = xs.foldl (fun a c => (a*d+val c)%q) acc := by
induction xs generalizing acc with
| nil => rfl
| cons c xs ih => simp [hashLoop, ih]@[simp] theorem hashLoop_characters (d q : Nat) (val : α → Nat) (acc : Nat) (xs : Text α) :
(hashLoop d q val acc xs).2 = xs.length := by
induction xs generalizing acc with
| nil => rfl
| cons c xs ih => simp [hashLoop, ih]
Two multiplications, two additions, one subtraction and two remainders.
def slide (d q high leading incoming h : Nat) : Nat :=
(d*h + incoming + q - (leading*high)%q)%q
With the prepared power, the fixed-operation slide equals the old recurrence.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.slide_eq`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem slide_eq (d q : Nat) (val : α → Nat) (h : Nat) (w : Text α) (c : α) :
slide d q (d^w.length) (val (w.headD default)) (val c) h = slideHash d q val h w c := rfl
structure Scan where
positions : List Nat
charges : Nat
slides : Natdef run (T P : Text α) (d q : Nat) (val : α → Nat) (high p m : Nat) :
Nat → Text α → Nat → Text α → Scan
| s,Variable name `w` is not explicitly referenced.
The binding can be removed (if unused) or named `_` (if used implicitly).
Note: This linter can be disabled with `set_option linter.unusedVariables false`w,h,[] => ⟨if h == p && matchesAt T P s then [s] else [],1+(if h==p then m else 0),0⟩
| s,w,h,c::rest =>
let next := slide d q high (val (w.headD default)) (val c) h
let tail := run T P d q val high p m (s+1) (w.tail++[c]) next rest
⟨if h==p && matchesAt T P s then s::tail.positions else tail.positions,
(if h==p then m else 0)+1+tail.charges,tail.slides+1⟩automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_slides`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_slides`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_slides`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_slides`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_slides`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
@[simp] automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_slides`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem run_slides (T P : Text α) (d q : Nat) (val : α → Nat)
(high p m s : Nat) (w : Text α) (h : Nat) (rest : Text α) :
(run T P d q val high p m s w h rest).slides = rest.length := by
induction rest generalizing s w h with
| nil => rfl
| cons c rest ih => simp [run, ih]automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.RKExecution.run_refines`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem run_refines (T P : Text α) (d q : Nat) (val : α → Nat)
(p m s : Nat) (w : Text α) (h : Nat) (rest : Text α)
(hm : 0 < m) (hw : w.length = m) :
let r := run T P d q val (d^m) p m s w h rest
(r.positions,r.charges) = rollingGo T P d q val p m s w h rest := by
induction rest generalizing s w h with
| nil => rfl
| cons c rest ih =>
have hw' : (w.tail++[c]).length = m := by simp [List.length_tail,hw]; omega
have hs : slide d q (d^m) (val (w.headD default)) (val c) h = slideHash d q val h w c := by
rw [← hw]; rfl
have hr := ih (s+1) (w.tail++[c]) (slideHash d q val h w c) hw'
simp only [run, hs, rollingGo]
rw [← hr]
split <;> rflstructure Result where
positions : List Nat
powerMultiplications : Nat
hashCharacters : Nat
slides : Nat
scanCharges : Natdef execute (T P : Text α) (d q : Nat) (val : α → Nat) : Result :=
if P.length = 0 then ⟨List.range (T.length+1),0,0,0,T.length+1⟩
else if T.length < P.length then ⟨[],0,0,0,0⟩
else
let high := power d P.length
let pattern := hashLoop d q val 0 P
let window := T.take P.length
let seed := hashLoop d q val 0 window
let output := run T P d q val high.1 pattern.1 P.length 0 window seed.1 (T.drop P.length)
⟨output.positions,high.2,pattern.2+seed.2,output.slides,output.charges⟩
Scalar preparation plus seven arithmetic primitives per slide and the
shift/confirmation budget. This is not the runtime of list copies or comparisons.
Both seed hashes and the prepared power are charged once.
theorem execute_preparation (T P : Text α) (d q : Nat) (val : α → Nat)
(hP : 0 < P.length) (hT : P.length ≤ T.length) :
(execute T P d q val).powerMultiplications = P.length ∧
(execute T P d q val).hashCharacters = 2 * P.length ∧
(execute T P d q val).slides = T.length - P.length := by
simp [execute, Nat.ne_of_gt hP, Nat.not_lt.mpr hT, List.length_take, Nat.min_eq_left hT,
Nat.two_mul]
theorem execute_refines (T P : Text α) (d q : Nat) (val : α → Nat)
(hP : 0 < P.length) (hT : P.length ≤ T.length) :
(execute T P d q val).positions = (rabinKarpRolling T P d q val).1 ∧
P.length + (execute T P d q val).scanCharges = (rabinKarpRolling T P d q val).2 := by
have hw : (T.take P.length).length = P.length := by simp [Nat.min_eq_left hT]
have hr := run_refines T P d q val (hash d q val P) P.length 0 (T.take P.length)
(hash d q val (T.take P.length)) (T.drop P.length) hP hw
have hpos := congrArg Prod.fst hr
have hcost := congrArg Prod.snd hr
simp only at hpos hcost
simp only [execute, Nat.ne_of_gt hP, Nat.not_lt.mpr hT, ↓reduceIte,
power_value, hashLoop_value, rabinKarpRolling]
change _ = _ ∧ _ = _
simp only [hash] at hpos hcost
exact ⟨hpos, congrArg (P.length + ·) hcost⟩
Actual cached-power execution returns every and only matching shift.
Exact connection to the established shift/confirmation charge, with newly
counted preparation and constant arithmetic per slide.
end CLRS.Chapter32.RKExecution
Imports
set_option maxHeartbeats 1000000
32.3. String Matching with Finite Automata
The finite-automaton string matcher (CLRS §32.3) builds a deterministic finite
automaton whose states are 0 … |P|, with transition δ(q, a) = σ(P_q a), the
length of the longest prefix of P that is a suffix of P_q a (here σ is the
suffix function of CLRS §32.3). After preprocessing, scanning the text with
δ accepts a prefix exactly when the pattern is a suffix of that prefix, so a
shift is recorded whenever the state reaches |P|.
Key definitions
-
suffixTest p t — decidable "is p a suffix of t".
-
suffixLen P x — the suffix function σ(x).
-
delta P q a — the transition δ(q, a).
-
deltaStar P q t — δ extended to a string.
Main results
-
Lemma 32.3 — σ(xa) ≤ σ(x) + 1 (suffixLen_snoc_le).
-
Lemma 32.4 — σ(xa) = σ(P_{σ(x)} a) (suffixLen_snoc_eq).
-
Theorem deltaStar_eq_suffixLen — δ*(q, T) = σ(P_q T).
-
Theorem deltaStar_accepts_iff_suffix — δ*(0, T) = |P| ↔ P is a suffix of T.
-
dfaMatcher — the all-occurrences automaton matcher, with
dfaMatcher_sound, dfaMatcher_complete, and dfaMatcher_correct
(equivalence to naiveMatcher).
-
transitionTable/transitionLookup — the finite-alphabet transition table,
with transitionLookup_eq_delta (lookup is exactly δ).
-
dfaMatcherTable — the table-driven matcher, refining dfaMatcher
(dfaMatcherTable_correct).
-
transitionTableBuildCost_eq / dfaMatcherCost_eq count table
cells and transition requests. They do not count suffix-search construction
or list/alphabet lookup runtime. CachedScan passes one constructed
table explicitly and counts the actual transition requests.
Notation conventions used in this section:
namespace CLRSnamespace Chapter32variable {α : Type} [BEq α] [DecidableEq α] [LawfulBEq α]
Decidable "is p a suffix of t", computed by checking the trailing
substring.
def suffixTest (p t : Text α) : Bool :=
if p.length ≤ t.length then (t.drop (t.length - p.length) == p) else false
suffixTest decides isSuffix.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_eq_isSuffix`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem suffixTest_eq_isSuffix (p t : Text α) :
suffixTest p t = true ↔ isSuffix p t := by
constructor
· intro h
unfold suffixTest at h
split at h
· next hlen =>
have hdrop : t.drop (t.length - p.length) = p := beq_iff_eq.mp h
refine ⟨t.take (t.length - p.length), ?_⟩
simpa [hdrop] using (List.take_append_drop (t.length - p.length) t)
· simp at h
· intro h
unfold suffixTest
have hlen : p.length ≤ t.length := isSuffix_length_le h
rw [if_pos hlen]
have hdrop : p = t.drop (t.length - p.length) := by
rcases h with ⟨s, hs⟩
have hlen' : s.length + p.length = t.length := by
simpa [List.length_append] using congrArg List.length hs
calc
p = (s ++ p).drop s.length := by simp
_ = t.drop s.length := by rw [hs]
_ = t.drop (t.length - p.length) := by
congr 1
omega
rw [← hdrop]
simp
If p is a suffix of t, then p = t.drop (t.length - p.length).
automatically included section variable(s) unused in theorem `CLRS.Chapter32.isSuffix_eq_drop`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.isSuffix_eq_drop`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.isSuffix_eq_drop`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.isSuffix_eq_drop`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.isSuffix_eq_drop`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.isSuffix_eq_drop`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.isSuffix_eq_drop`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.isSuffix_eq_drop`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.isSuffix_eq_drop`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.isSuffix_eq_drop`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.isSuffix_eq_drop`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.isSuffix_eq_drop`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.isSuffix_eq_drop`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma isSuffix_eq_drop {p t : Text α} (h : isSuffix p t) : p = t.drop (t.length - p.length) := by
rcases h with ⟨s, hs⟩
have hlen : s.length + p.length = t.length := by
simpa [List.length_append] using congrArg List.length hs
calc
p = (s ++ p).drop s.length := by simp
_ = t.drop s.length := by rw [hs]
_ = t.drop (t.length - p.length) := by
congr 1
omega
p is a suffix of t → p ++ u is a suffix of t ++ u.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_append_right`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_append_right`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_append_right`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_append_right`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_append_right`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_append_right`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_append_right`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma suffix_append_right {p t u : Text α} (h : isSuffix p t) : isSuffix (p ++ u) (t ++ u) := by
rcases h with ⟨s, hs⟩
refine ⟨s, ?_⟩
rw [← List.append_assoc, hs]
automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_trans`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_trans`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_trans`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_trans`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_trans`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_trans`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_trans`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_trans`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_trans`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma suffix_trans {r s t : Text α} (hrs : isSuffix r s) (hst : isSuffix s t) : isSuffix r t := by
rcases hrs with ⟨p, hp⟩
rcases hst with ⟨q, hq⟩
refine ⟨q ++ p, ?_⟩
rw [List.append_assoc, hp, hq]
If y and z are both suffixes of x and z.length ≤ y.length, then z
is a suffix of y.
lemma isSuffix_of_suffix_of_suffix {x y z : Text α} (hy : isSuffix y x) (hz : isSuffix z x)
(hlen : z.length ≤ y.length) : isSuffix z y := by
have hylen : y.length ≤ x.length := isSuffix_length_le hy
have hzlen : z.length ≤ x.length := isSuffix_length_le hz
rw [isSuffix_eq_drop hy, isSuffix_eq_drop hz]
refine ⟨(x.drop (x.length - y.length)).take (y.length - z.length), ?_⟩
rw [show List.drop (x.length - z.length) x = List.drop (y.length - z.length) (List.drop (x.length - y.length) x) by
rw [List.drop_drop]
congr 1
omega]
exact List.take_append_drop (y.length - z.length) (List.drop (x.length - y.length) x)
The suffix function search: largest k ≤ n with P.take k a suffix of x.
The suffix function σ(x): the largest k ≤ |P| with P.take k a suffix
of x (CLRS §32.3).
suffixLenAux never exceeds its bound.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma suffixLenAux_le (P x : Text α) (n : ℕ) : suffixLenAux P x n ≤ n := by
induction n with
| zero => simp [suffixLenAux]
| succ n ih =>
by_cases ht : suffixTest (P.take (n + 1)) x
· simp [suffixLenAux, ht]
· simp [suffixLenAux, ht]; omega
P.take (σ x) is a suffix of x.
try 'simp' instead of 'simpa'
Note: This linter can be disabled with `set_option linter.unnecessarySimpa false`
theorem suffixLen_satisfies (P x : Text α) : isSuffix (P.take (suffixLen P x)) x := by
unfold suffixLen
have hgo : ∀ n, suffixLenAux P x n = 0 ∨ suffixTest (P.take (suffixLenAux P x n)) x = true := by
intro n
induction n with
| zero => left; simp [suffixLenAux]
| succ n ih =>
by_cases ht : suffixTest (P.take (n + 1)) x
· right; try 'simp' instead of 'simpa'
Note: This linter can be disabled with `set_option linter.unnecessarySimpa false`simpa [suffixLenAux, ht] using ht
· simpa [suffixLenAux, ht] using ih
rcases hgo P.length with hzero | hsuf
· rw [hzero]; exact isSuffix_empty x
· exact (suffixTest_eq_isSuffix _ _).mp hsuf
σ(x) is maximal: any k ≤ |P| whose P.take k is a suffix of x
satisfies k ≤ σ(x).
Try `simp at ht` instead of `simpa using ht`
Note: This linter can be disabled with `set_option linter.unnecessarySimpa false`
theorem suffixLen_maximal (P x : Text α) (k : ℕ) (hk : k ≤ P.length)
(hsuf : isSuffix (P.take k) x) : k ≤ suffixLen P x := by
unfold suffixLen
have ht : suffixTest (P.take k) x = true := (suffixTest_eq_isSuffix _ _).mpr hsuf
have hgo : ∀ n, k ≤ n → k ≤ suffixLenAux P x n := by
intro n hkn
induction n with
| zero => omega
| succ n ih =>
by_cases hts : suffixTest (P.take (n + 1)) x
· simp [suffixLenAux, hts]
omega
· have hklt : k < n + 1 := by
by_cases hk_eq : k = n + 1
· subst k; Try `simp at ht` instead of `simpa using ht`
Note: This linter can be disabled with `set_option linter.unnecessarySimpa false`simpa [hts] using ht
· omega
have := ih (by omega)
simpa [suffixLenAux, hts] using this
exact hgo P.length hk
The suffix function at a prefix of P returns that prefix's length.
If P.take r is a suffix of x ++ [a] with 0 < r, then P.take (r-1)
is a suffix of x.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_dropLast_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma suffix_dropLast_of_snoc (P x : Text α) (r : ℕ) (a : α) (hr : 0 < r) (hk : r ≤ P.length)
(hsuf : isSuffix (P.take r) (x ++ [a])) : isSuffix (P.take (r - 1)) x := by
rcases hsuf with ⟨s, hs⟩
have hdropLast : (P.take r).dropLast = P.take (r - 1) := by
rw [List.dropLast_eq_take]
have hlen : (P.take r).length = r := by rw [List.length_take]; exact Nat.min_eq_left hk
rw [hlen, List.take_take, Nat.min_eq_left (by omega)]
refine ⟨s, ?_⟩
have hne : (P.take r) ≠ [] := by
have hlenr : (P.take r).length = r := by rw [List.length_take]; exact Nat.min_eq_left hk
intro he
have h0 : (P.take r).length = 0 := by simp [he]
omega
have hd : s ++ P.take (r - 1) = x := by
have h1 : (s ++ P.take r).dropLast = (x ++ [a]).dropLast := by rw [hs]
rw [List.dropLast_concat] at h1
have h2 : (s ++ P.take r).dropLast = s ++ P.take (r - 1) := by
rw [List.dropLast_append]
by_cases h : (P.take r).isEmpty = true
· have : P.take r = [] := (List.isEmpty_iff.mp h)
exact (hne this).elim
· simp [h, hdropLast]
rw [h2] at h1
exact h1
exact hd
If P.take r is a suffix of x ++ [a] and 0 < r ≤ |P|, then the last
character of P.take r is a.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffix_last_char_of_snoc`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma suffix_last_char_of_snoc (P x : Text α) (r : ℕ) (a : α)
(hsuf : isSuffix (P.take r) (x ++ [a])) (hrpos : 0 < r) (hk : r ≤ P.length) :
(P.take r).getLast? = some a := by
rcases hsuf with ⟨s, hs⟩
have hne : P.take r ≠ [] := by
have hlenr : (P.take r).length = r := by rw [List.length_take]; exact Nat.min_eq_left hk
intro he
have h0 : (P.take r).length = 0 := by simp [he]
omega
have hlast : (s ++ P.take r).getLast? = some a := by
rw [hs, List.getLast?_concat]
have hrel : (s ++ P.take r).getLast? = (P.take r).getLast? := by
rw [List.getLast?_append]
rw [show (P.take r).getLast? = some ((P.take r).getLast hne) from `List.getLast?_eq_getLast` has been deprecated: Use `List.getLast?_eq_some_getLast` insteadList.getLast?_eq_getLast hne]
simp
rw [hrel] at hlast
exact hlast
P.take r = P.take (r-1) ++ [a] when (P.take r) ends in a.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_eq_take_pred_append`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma take_eq_take_pred_append (P : Text α) (r : ℕ) (a : α) (hrpos : 0 < r) (hk : r ≤ P.length)
(hchar : (P.take r).getLast? = some a) : P.take r = P.take (r - 1) ++ [a] := by
have hne : P.take r ≠ [] := by
have hlenr : (P.take r).length = r := by rw [List.length_take]; exact Nat.min_eq_left hk
intro he
have h0 : (P.take r).length = 0 := by simp [he]
omega
have hgetLast : (P.take r).getLast hne = a := by
have := hchar
rw [`List.getLast?_eq_getLast` has been deprecated: Use `List.getLast?_eq_some_getLast` insteadList.getLast?_eq_getLast hne] at this
exact Option.some.inj this
rw [← List.dropLast_append_getLast hne]
rw [hgetLast]
congr 1
rw [List.dropLast_eq_take]
have hlenr : (P.take r).length = r := by rw [List.length_take]; exact Nat.min_eq_left hk
rw [hlenr, List.take_take]
rw [Nat.min_eq_left (by omega)]
CLRS Lemma 32.3: σ(xa) ≤ σ(x) + 1.
CLRS Lemma 32.4: σ(xa) = σ(P_{σ(x)} a).
σ(y T) = σ(P_{σ(y)} T): the suffix function of an extended string only
depends on the longest prefix-suffix of the base.
The transition function δ(q, a) = σ(P_q a) (CLRS §32.3).
def delta (P : Text α) (q : ℕ) (a : α) : ℕ :=
suffixLen P (P.take q ++ [a])
δ extended to a string: δ*(q, T) = foldl δ q T.
def deltaStar (P : Text α) (q : ℕ) : Text α → ℕ :=
List.foldl (delta P) q
@[simp] automatically included section variable(s) unused in theorem `CLRS.Chapter32.deltaStar_nil`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem deltaStar_nil (P : Text α) (q : ℕ) : deltaStar P q [] = q := rfl@[simp] automatically included section variable(s) unused in theorem `CLRS.Chapter32.deltaStar_cons`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem deltaStar_cons (P : Text α) (q : ℕ) (a : α) (T : Text α) :
deltaStar P q (a :: T) = deltaStar P (delta P q a) T := rfl
The automaton (from state 0) reaches state |P| exactly when P is a
suffix of the input.
δ*(0, x) = σ(x) never exceeds the length of its input.
The empty pattern is never a proper suffix: δ* from 0 stays at 0.
Appending one character to the scanned text advances δ* by one transition.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.deltaStar_append_one`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.deltaStar_append_one`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.deltaStar_append_one`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.deltaStar_append_one`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.deltaStar_append_one`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.deltaStar_append_one`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma deltaStar_append_one (P : Text α) (scanned : Text α) (c : α) :
deltaStar P 0 (scanned ++ [c]) = delta P (deltaStar P 0 scanned) c := by
change List.foldl (delta P) 0 (scanned ++ [c]) = delta P (List.foldl (delta P) 0 scanned) c
rw [List.foldl_append]
rfl
range (n + 2) is 0 followed by range (n + 1) shifted by one.
lemma range_succ_cons (n : ℕ) :
List.range (n + 2) = 0 :: (List.range (n + 1)).map (fun k => 1 + k) := by
conv_lhs => rw [show n + 2 = 1 + (n + 1) by omega]
rw [List.range_add]
simp only [List.range_one, List.singleton_append]
@[simp] automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_cons_zero`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma take_cons_zero (c : α) (T : Text α) : (c :: T).take 0 = [] := rflautomatically included section variable(s) unused in theorem `CLRS.Chapter32.take_cons_succ_one`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_cons_succ_one`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_cons_succ_one`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_cons_succ_one`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_cons_succ_one`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_cons_succ_one`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_cons_succ_one`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.take_cons_succ_one`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma take_cons_succ_one (c : α) (T : Text α) (k : ℕ) : (c :: T).take (1 + k) = c :: T.take k := by
rw [List.take_cons (by omega : 0 < 1 + k)]
rw [show (1 + k) - 1 = k by omega]
The finite-automaton scan (CLRS FINITE-AUTOMATON-MATCHER). scanned is the
text already scanned, q = δ*(0, scanned) the current state, and m = |P|.
It returns, in increasing order, every shift scanned.length - m at which the
state has reached m, i.e. every shift where P matches the text.
def dfaScan (P : Text α) (m : ℕ) (scanned : Text α) (q : ℕ) : Text α → List ℕ
| [] => if q == m then [scanned.length - m] else []
| c :: rest =>
let q' := delta P q c
let tail := dfaScan P m (scanned ++ [c]) q' rest
if q == m then (scanned.length - m) :: tail else tail
@[simp] automatically included section variable(s) unused in theorem `CLRS.Chapter32.dfaScan_nil`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma dfaScan_nil (P : Text α) (m : ℕ) (scanned : Text α) (q : ℕ) :
dfaScan P m scanned q [] = (if q == m then [scanned.length - m] else []) := rflautomatically included section variable(s) unused in theorem `CLRS.Chapter32.dfaScan_cons`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.dfaScan_cons`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.dfaScan_cons`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.dfaScan_cons`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.dfaScan_cons`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma dfaScan_cons (P : Text α) (m : ℕ) (scanned : Text α) (q : ℕ) (c : α) (T : Text α) :
dfaScan P m scanned q (c :: T)
= (if q == m then [scanned.length - m] else [])
++ dfaScan P m (scanned ++ [c]) (delta P q c) T := by
by_cases h : q == m <;> simp [dfaScan, h]
The tail of the scan specification: the composed shift/state functions
rewrite to the RHS functions.
lemma dfaScan_spec_tail (P : Text α) (m : ℕ) (scanned : Text α) (c : α) (T : Text α) :
List.map ((fun j => scanned.length + j - m) ∘ (fun k => 1 + k))
(List.filter ((fun j => deltaStar P 0 (scanned ++ (c :: T).take j) == m) ∘ (fun k => 1 + k)) (List.range (T.length + 1)))
= List.map (fun j => (scanned ++ [c]).length + j - m)
(List.filter (fun j => deltaStar P 0 ((scanned ++ [c]) ++ T.take j) == m) (List.range (T.length + 1))) := by
have hp : ((fun j => deltaStar P 0 (scanned ++ (c :: T).take j) == m) ∘ (fun k => 1 + k))
= (fun j => deltaStar P 0 ((scanned ++ [c]) ++ T.take j) == m) := by
funext j
simp [take_cons_succ_one, List.append_assoc]
have hf : ((fun j => scanned.length + j - m) ∘ (fun k => 1 + k))
= (fun j => (scanned ++ [c]).length + j - m) := by
funext j
simp [List.length_append]
omega
rw [hp, hf]
The RHS of the scan specification, decomposed across one consumed character.
lemma dfaScan_spec_cons (P : Text α) (m : ℕ) (scanned : Text α) (c : α) (T : Text α) :
((List.range ((c :: T).length + 1)).filter (fun j => deltaStar P 0 (scanned ++ (c :: T).take j) == m)).map
(fun j => scanned.length + j - m)
= (if deltaStar P 0 scanned == m then [scanned.length - m] else [])
++ ((List.range (T.length + 1)).filter (fun j => deltaStar P 0 ((scanned ++ [c]) ++ T.take j) == m)).map
(fun j => (scanned ++ [c]).length + j - m) := by
change ((List.range (T.length + 2)).filter (fun j => deltaStar P 0 (scanned ++ (c :: T).take j) == m)).map
(fun j => scanned.length + j - m)
= (if deltaStar P 0 scanned == m then [scanned.length - m] else [])
++ ((List.range (T.length + 1)).filter (fun j => deltaStar P 0 ((scanned ++ [c]) ++ T.take j) == m)).map
(fun j => (scanned ++ [c]).length + j - m)
rw [range_succ_cons T.length]
simp only [List.filter_cons, This simp argument is unused:
List.map_cons
Hint: Omit it from the simp argument list.
simp only [List.filter_cons, List.m̵a̵p̵_̵c̵o̵n̵s̵,̵ ̵L̵i̵s̵t̵.̵filter_nil, List.map_nil, List.map_append]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`List.map_cons, This simp argument is unused:
List.filter_nil
Hint: Omit it from the simp argument list.
simp only [List.filter_cons, List.map_cons, List.f̵i̵l̵t̵e̵r̵_̵n̵i̵l̵,̵ ̵L̵i̵s̵t̵.̵map_nil, List.map_append]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`List.filter_nil, This simp argument is unused:
List.map_nil
Hint: Omit it from the simp argument list.
simp only [List.filter_cons, List.map_cons, List.filter_nil, List.map_n̵i̵l̵,̵ ̵L̵i̵s̵t̵.̵m̵ap_̵a̵pp̵end]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`List.map_nil, This simp argument is unused:
List.map_append
Hint: Omit it from the simp argument list.
simp only [List.filter_cons, List.map_cons, List.filter_nil, List.map_nil,̵ ̵L̵i̵s̵t̵.̵m̵a̵p̵_̵a̵p̵p̵e̵n̵d̵]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`List.map_append]
simp only [List.filter_map]
by_cases h : deltaStar P 0 scanned = m <;> simp [h, List.map_map, List.append_nil] <;> rw [dfaScan_spec_tail P m scanned c T] <;> simp
The automaton scan from a scanned whose state is δ*(0, scanned) returns exactly
the shifts scanned.length + j - m for end positions scanned.length + j whose
scanned text scanned ++ T.take j reaches state m.
lemma dfaScan_spec (P : Text α) (m : ℕ) (scanned T : Text α) :
dfaScan P m scanned (deltaStar P 0 scanned) T
= ((List.range (T.length + 1)).filter (fun j => deltaStar P 0 (scanned ++ T.take j) == m)).map
(fun j => scanned.length + j - m) := by
induction T generalizing scanned with
| nil =>
simp [dfaScan, List.append_nil, This simp argument is unused:
List.take_zero
Hint: Omit it from the simp argument list.
simp [dfaScan, List.append_nil, List.t̵a̵k̵e̵_̵z̵e̵ro̵,̵ ̵L̵i̵s̵t̵.̵r̵ange_one, List.filter_cons, List.map_cons]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`List.take_zero, List.range_one, List.filter_cons, This simp argument is unused:
List.map_cons
Hint: Omit it from the simp argument list.
simp [dfaScan, List.append_nil, List.take_zero, List.range_one, List.filter_cons,̵ ̵L̵i̵s̵t̵.̵m̵a̵p̵_̵c̵o̵n̵s̵]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`List.map_cons]
by_cases h : deltaStar P 0 scanned = m <;> simp [h]
| cons c T ih =>
rw [dfaScan_cons, ← deltaStar_append_one P scanned c]
rw [ih (scanned ++ [c])]
exact (dfaScan_spec_cons P m scanned c T).symm
The finite-automaton matcher: scan T left-to-right maintaining the automaton
state, recording every shift where the state reaches |P|. This is the
all-occurrences DFA matcher of CLRS §32.3.
def dfaMatcher (P T : Text α) : List ℕ :=
dfaScan P P.length [] 0 T
The automaton matcher, expressed as an end-position filter-map.
theorem dfaMatcher_spec (P T : Text α) :
dfaMatcher P T
= ((List.range (T.length + 1)).filter (fun j => deltaStar P 0 (T.take j) == P.length)).map
(fun j => j - P.length) := by
unfold dfaMatcher
simpa using (dfaScan_spec P P.length [] T)
A real match at shift s is exactly a suffix of the (s + |P|)-scanned.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.matchesAt_iff_isSuffix_take`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma matchesAt_iff_isSuffix_take (P T : Text α) (s : ℕ) (hs : s + P.length ≤ T.length) :
matchesAt T P s = true ↔ isSuffix P (T.take (s + P.length)) := by
unfold matchesAt
rw [if_pos hs, beq_iff_eq]
constructor
· intro h
refine ⟨T.take s, ?_⟩
rw [List.take_add (i := s) (j := P.length) (l := T), h]
· intro h
rcases h with ⟨u, hu⟩
have hulen : u.length = s := by
have hlen := congrArg List.length hu
rw [List.length_append, List.length_take] at hlen
have hmin : min (s + P.length) T.length = s + P.length := Nat.min_eq_left hs
rw [hmin] at hlen
omega
calc
(T.drop s).take P.length = (T.take (s + P.length)).drop s := by
rw [List.drop_take]; simp
_ = (u ++ P).drop s := by rw [← hu]
_ = (u ++ P).drop u.length := by rw [hulen]
_ = P := List.drop_left
δ*(0, T.take (s + |P|)) accepting agrees with matchesAt T P s.
lemma deltaStar_take_eq_matchesAt (P T : Text α) (s : ℕ) (hs : s + P.length ≤ T.length) :
(deltaStar P 0 (T.take (s + P.length)) == P.length) = matchesAt T P s := by
have hacc : (deltaStar P 0 (T.take (s + P.length)) = P.length) ↔ (matchesAt T P s = true) := by
constructor
· intro hd
have hsuf := (deltaStar_accepts_iff_suffix P (T.take (s + P.length))).mp hd
exact (matchesAt_iff_isSuffix_take P T s hs).mpr hsuf
· intro hm
have hsuf := (matchesAt_iff_isSuffix_take P T s hs).mp hm
exact (deltaStar_accepts_iff_suffix P (T.take (s + P.length))).mpr hsuf
cases h : matchesAt T P s with
| true =>
have hd : deltaStar P 0 (T.take (s + P.length)) = P.length := hacc.mpr h
simp [hd, This simp argument is unused:
beq_iff_eq
Hint: Omit it from the simp argument list.
simp [hd,̵ ̵b̵e̵q̵_̵i̵f̵f̵_̵e̵q̵]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`beq_iff_eq]
| false =>
have hd : deltaStar P 0 (T.take (s + P.length)) ≠ P.length := by
intro hd'
have htrue : matchesAt T P s = true := hacc.mp hd'
rw [h] at htrue
cases htrue
cases hb : deltaStar P 0 (T.take (s + P.length)) == P.length with
| true =>
have heq : deltaStar P 0 (T.take (s + P.length)) = P.length := beq_iff_eq.mp hb
exact (hd heq).elim
| false =>
rfl
The end-position filter-map of the automaton matcher equals the shift-domain
naiveMatcher result.
lemma filter_map_delta_eq_naive (P T : Text α) :
((List.range (T.length + 1)).filter (fun j => deltaStar P 0 (T.take j) == P.length)).map
(fun j => j - P.length) = naiveMatcher T P := by
by_cases hzero : P.length = 0
· have hnil : P = [] := List.eq_nil_of_length_eq_zero hzero
subst P
simp [naiveMatcher_empty, deltaStar_empty]
· have hm0 : 0 < P.length := Nat.pos_of_ne_zero hzero
by_cases hle : P.length ≤ T.length
· have hrange : List.range (T.length + 1)
= List.range P.length ++ List.map (fun x => P.length + x) (List.range (T.length - P.length + 1)) := by
have h := List.range_add (n := P.length) (m := T.length - P.length + 1)
rw [show P.length + (T.length - P.length + 1) = T.length + 1 by omega] at h
exact h
rw [hrange, List.filter_append, List.map_append]
have hfilt1 : (List.range P.length).filter (fun j => deltaStar P 0 (T.take j) == P.length) = [] := by
rw [List.eq_nil_iff_forall_not_mem]
intro j hj
rw [List.mem_filter] at hj
rcases hj with ⟨hjr, hjp⟩
have hjm : j < P.length := List.mem_range.mp hjr
have hd : deltaStar P 0 (T.take j) ≤ j := by
exact le_trans (deltaStar_le_length P (T.take j)) (by rw [List.length_take]; exact Nat.min_le_left _ _)
have hbad : deltaStar P 0 (T.take j) = P.length := beq_iff_eq.mp hjp
have hle' : P.length ≤ j := by simpa [hbad] using hd
omega
rw [hfilt1, List.map_nil, List.nil_append]
rw [List.filter_map, List.map_map]
have hsub : (fun x => (P.length + x) - P.length) = (fun x => x) := by
funext x; rw [Nat.add_sub_cancel_left]
change List.map (fun x => (P.length + x) - P.length)
((List.range (T.length - P.length + 1)).filter (fun x => deltaStar P 0 (T.take (P.length + x)) == P.length))
= naiveMatcher T P
simp [This simp argument is unused:
hsub
Hint: Omit it from the simp argument list.
simp ̵[̵h̵s̵u̵b̵]̵
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`hsub]
rw [naiveMatcher, if_neg hzero]
apply List.filter_congr
intro s hs
have hsle : s + P.length ≤ T.length := by
have := List.mem_range.mp hs
omega
rw [show P.length + s = s + P.length by omega]
exact deltaStar_take_eq_matchesAt P T s hsle
· have hlong : T.length < P.length := Nat.lt_of_not_ge hle
have hfilt : (List.range (T.length + 1)).filter (fun j => deltaStar P 0 (T.take j) == P.length) = [] := by
rw [List.eq_nil_iff_forall_not_mem]
intro j hj
rw [List.mem_filter] at hj
rcases hj with ⟨hjr, hjp⟩
have hjn : j < T.length + 1 := List.mem_range.mp hjr
have hd : deltaStar P 0 (T.take j) ≤ j := by
exact le_trans (deltaStar_le_length P (T.take j)) (by rw [List.length_take]; exact Nat.min_le_left _ _)
have hbad : deltaStar P 0 (T.take j) = P.length := beq_iff_eq.mp hjp
have hle' : P.length ≤ j := by simpa [hbad] using hd
omega
rw [hfilt, List.map_nil]
simpa [noMatch] using (naiveMatcher_pattern_too_long T P hlong).symm
Correctness of the finite-automaton matcher. dfaMatcher P T returns
exactly the shifts that naiveMatcher T P returns, for every pattern and text.
Every shift returned by the automaton matcher is a valid match.
Every valid match is returned by the automaton matcher.
Transition-request budget: one per text character. This does not count
transition computation, alphabet indexing or list-table access.
def dfaMatcherCost (Variable name `P` is not explicitly referenced.
The binding can be removed (if unused) or named `_` (if used implicitly).
Note: This linter can be disabled with `set_option linter.unusedVariables false`P T : Text α) : ℕ := T.length
The automaton matcher scans each character once.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.dfaMatcherCost_eq`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem dfaMatcherCost_eq (P T : Text α) : dfaMatcherCost P T = T.length := rfl
section TransitionTable
The transition table for pattern P over a finite alphabet alphabet (CLRS
§32.3 COMPUTE-TRANSITION-FUNCTION): one row per state q ∈ [0, |P|], each row
listing the precomputed next-state δ(q, a) for every a ∈ alphabet, in
row-major order.
def transitionTable (alphabet : List α) (P : Text α) : List (List ℕ) :=
(List.range (P.length + 1)).map (fun q => alphabet.map (fun a => delta P q a))
Look up the next state for state q and symbol a in a transition table
indexed by alphabet, returning 0 for an out-of-range state or symbol.
def transitionLookup (alphabet : List α) (table : List (List ℕ)) (q : ℕ) (a : α) : ℕ :=
(table.getD q []).getD (alphabet.idxOf a) 0
The transition table has one row per state.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionTable_length`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionTable_length`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionTable_length`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionTable_length`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem transitionTable_length (alphabet : List α) (P : Text α) :
(transitionTable alphabet P).length = P.length + 1 := by
unfold transitionTable
simp
The table lookup agrees with the semantic transition δ: for every state
q ≤ |P| and every symbol a in the alphabet, the entry stored in
transitionTable alphabet P at (q, a) is exactly δ(q, a).
automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionLookup_eq_delta`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem transitionLookup_eq_delta (alphabet : List α) (P : Text α) (q : ℕ) (hq : q ≤ P.length) (a : α)
(ha : a ∈ alphabet) :
transitionLookup alphabet (transitionTable alphabet P) q a = delta P q a := by
unfold transitionLookup transitionTable
have hrow : ((List.range (P.length + 1)).map (fun q => alphabet.map (fun a => delta P q a))).getD q []
= alphabet.map (fun a => delta P q a) := by
rw [List.getD_eq_getElem]
· rw [List.getElem_map, List.getElem_range]
· rw [List.length_map, List.length_range]
omega
rw [hrow]
have hlt : alphabet.idxOf a < alphabet.length := (List.idxOf_lt_length_iff).mpr ha
have hlen : alphabet.idxOf a < (alphabet.map (fun a => delta P q a)).length := by
simpa using hlt
rw [List.getD_eq_getElem (l := alphabet.map (fun a => delta P q a)) (d := 0) (n := alphabet.idxOf a) hlen]
rw [List.getElem_map]
rw [List.getElem_idxOf hlt]
The table-driven scan: the same left-to-right scan as dfaScan, but each
transition uses a table expression. This legacy definition contains table
construction inside each recursive call; CachedScan instead accepts a
previously constructed table as an explicit parameter.
def dfaScanTable (alphabet : List α) (P : Text α) (m : ℕ) (scanned : Text α) (q : ℕ) : Text α → List ℕ
| [] => if q == m then [scanned.length - m] else []
| c :: rest =>
let q' := transitionLookup alphabet (transitionTable alphabet P) q c
let tail := dfaScanTable alphabet P m (scanned ++ [c]) q' rest
if q == m then (scanned.length - m) :: tail else tail
automatically included section variable(s) unused in theorem `CLRS.Chapter32.dfaScanTable_cons`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.dfaScanTable_cons`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.dfaScanTable_cons`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.dfaScanTable_cons`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.dfaScanTable_cons`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma dfaScanTable_cons (alphabet : List α) (P : Text α) (m : ℕ) (scanned : Text α) (q : ℕ) (c : α) (T : Text α) :
dfaScanTable alphabet P m scanned q (c :: T)
= (if q == m then [scanned.length - m] else [])
++ dfaScanTable alphabet P m (scanned ++ [c]) (transitionLookup alphabet (transitionTable alphabet P) q c) T := by
by_cases h : q == m <;> simp [dfaScanTable, h]
The table-driven matcher (CLRS FINITE-AUTOMATON-MATCHER with precomputed
δ): the reference scan over a table expression. List lookup and
alphabet indexing do not provide constant-time transitions.
def dfaMatcherTable (alphabet : List α) (P T : Text α) : List ℕ :=
dfaScanTable alphabet P P.length [] 0 T
The table-driven scan agrees with the semantic scan when every state is in
range and every scanned character is in the alphabet.
The table-driven matcher refines the semantic automaton matcher over a finite
alphabet: when every character of T lies in alphabet, the two return exactly
the same shifts.
The table-driven matcher returns exactly the shifts of naiveMatcher when the
text stays within the alphabet.
Table-cell count, excluding the suffix-search work used to compute each
transition and excluding allocation costs.
def transitionTableBuildCost (alphabet : List α) (P : Text α) : ℕ :=
((transitionTable alphabet P).map List.length).sum
The table has (|P| + 1) * |alphabet| cells, one per state/symbol pair.
This does not prove that the suffix-search builder runs in that many operations.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionTableBuildCost_eq`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionTableBuildCost_eq`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionTableBuildCost_eq`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionTableBuildCost_eq`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionTableBuildCost_eq`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionTableBuildCost_eq`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.transitionTableBuildCost_eq`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem transitionTableBuildCost_eq (alphabet : List α) (P : Text α) :
transitionTableBuildCost alphabet P = (P.length + 1) * alphabet.length := by
unfold transitionTableBuildCost transitionTable
rw [List.map_map]
change ((List.range (P.length + 1)).map (fun q => List.length (alphabet.map (fun a => delta P q a)))).sum
= (P.length + 1) * alphabet.length
simp [List.length_map, List.length_range, List.sum_replicate]
Sum of the table-cell and transition-request budgets, not total runtime.
end TransitionTableend Chapter32end CLRS
Definitions and proofs
One constructed transition table and a counted scan
The table is an explicit scan parameter and is built once by the matcher.
Counters count table cells and transition requests only. Suffix search inside
delta, alphabet indexing and list-table lookup are not constant-time
operations in this representation, so these counts are not construction or
machine-runtime bounds.
namespace CLRS.Chapter32.DFAExecutionvariable {α : Type} [BEq α] [DecidableEq α] [LawfulBEq α]structure Scan where
positions : List Nat
transitions : Natdef scan (alphabet : List α) (table : List (List Nat)) (m : Nat) : Nat → Nat → Text α → Scan
| processed, q, [] => ⟨if q == m then [processed-m] else [],0⟩
| processed, q, c :: rest =>
let next := transitionLookup alphabet table q c
let tail := scan alphabet table m (processed+1) next rest
⟨if q == m then (processed-m)::tail.positions else tail.positions, tail.transitions+1⟩omit [DecidableEq α] [LawfulBEq α] in
@[simp] theorem scan_transitions (alphabet : List α) (table : List (List Nat))
(m processed q : Nat) (xs : Text α) :
(scan alphabet table m processed q xs).transitions = xs.length := by
induction xs generalizing processed q with
| nil => rfl
| cons c xs ih => simp [scan, ih]omit [DecidableEq α] [LawfulBEq α] in
theorem scan_refines (alphabet : List α) (P : Text α) (m : Nat) (scanned : Text α)
(q : Nat) (xs : Text α) :
(scan alphabet (transitionTable alphabet P) m scanned.length q xs).positions =
dfaScanTable alphabet P m scanned q xs := by
induction xs generalizing scanned q with
| nil => rfl
| cons c xs ih =>
simp only [scan, dfaScanTable]
have h := ih (scanned ++ [c]) (transitionLookup alphabet (transitionTable alphabet P) q c)
simpa using congrArg (fun tail => if q == m then (scanned.length-m)::tail else tail) hstructure Result where
table : List (List Nat)
positions : List Nat
cells : Nat
transitions : Natdef execute (alphabet : List α) (P T : Text α) : Result :=
let table := transitionTable alphabet P
let output := scan alphabet table P.length 0 0 T
⟨table, output.positions, (table.map List.length).sum, output.transitions⟩@[simp] automatically included section variable(s) unused in theorem `CLRS.Chapter32.DFAExecution.execute_transitions`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem execute_transitions (alphabet : List α) (P T : Text α) :
(execute alphabet P T).transitions = T.length := scan_transitions _ _ _ _ _ _@[simp] theorem execute_cells (alphabet : List α) (P T : Text α) :
(execute alphabet P T).cells = (P.length + 1) * alphabet.length :=
transitionTableBuildCost_eq _ _theorem execute_correct (alphabet : List α) (P T : Text α) (hT : ∀ c ∈ T, c ∈ alphabet) :
(execute alphabet P T).positions = naiveMatcher T P := by
have h := scan_refines alphabet P P.length [] 0 T
change (scan alphabet (transitionTable alphabet P) P.length 0 0 T).positions = _
exact h.trans (dfaMatcherTable_eq_naive alphabet P T hT)end CLRS.Chapter32.DFAExecution
Imports
set_option maxHeartbeats 1000000
32.4. The Knuth–Morris–Pratt Algorithm
The Knuth–Morris–Pratt algorithm (CLRS §32.4) finds all occurrences of a
pattern P in a text T in time O(|P| + |T|) by precomputing a prefix
function π on the pattern, then scanning the text once, falling back along
π whenever a match attempt fails.
Key definitions
-
prefixLen P q — the prefix function π[q]: the longest proper prefix
of P that is a suffix of P.take q.
-
computePrefixFunction P — the executable COMPUTE-PREFIX-FUNCTION
(failure-link recurrence), returning the prefix array.
-
kmpMatcher P T — the executable all-occurrences KMP-MATCHER scan.
Main results
-
prefixLen_satisfies / prefixLen_maximal — P.take (π q) is the longest
proper prefix of P that is a suffix of P.take q.
-
prefixLen_chain_step — the CLRS Lemma 32.5 induction step: a shorter
prefix-suffix of P.take q is a prefix-suffix of P.take (π q).
-
prefixLen_snoc_eq — the CLRS Lemma 32.6 recurrence: π(q + 1) extends the
longest prefix-suffix of P.take q whose next character matches P[q].
-
failureFollow_eq_prefixMatchAux — following failure links from π(q) agrees
with the from-scratch search.
-
computePrefixFunction_correct — each entry of the executable array equals
prefixLen (CLRS Lemma 32.6).
-
kmpStep_eq_delta — one executable scan step computes the automaton
transition δ(q, a).
-
kmpMatcher_correct — kmpMatcher P T agrees with naiveMatcher T P
(all and only matches), with kmpMatcher_sound/kmpMatcher_complete.
-
kmpTotalCost_le — the costed prefix construction plus costed scan runs in
linear time O(|P| + |T|).
Notation conventions used in this section:
namespace CLRSnamespace Chapter32variable {α : Type} [BEq α] [DecidableEq α] [LawfulBEq α] [Inhabited α]
Search for the largest k ≤ n such that P.take k is a suffix of x.
The prefix function π(q): the longest proper prefix of P that is a
suffix of P.take q (CLRS §32.4). Bounded by q - 1 so it is always proper.
prefixLenAux never exceeds its bound.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLenAux_le`:
[DecidableEq α]
[LawfulBEq α]
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma prefixLenAux_le (P x : Text α) (n : ℕ) : prefixLenAux P x n ≤ n := by
induction n with
| zero => simp [prefixLenAux]
| succ n ih =>
by_cases h : suffixTest (P.take (n + 1)) x
· simp [prefixLenAux, h]
· simp [prefixLenAux, h]; omega
The prefix function never exceeds its index.
The prefix function is proper when its index is positive.
P.take (π q) is a suffix of P.take q.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`try 'simp' instead of 'simpa'
Note: This linter can be disabled with `set_option linter.unnecessarySimpa false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_satisfies`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem prefixLen_satisfies (P : Text α) (q : ℕ) :
isSuffix (P.take (prefixLen P q)) (P.take q) := by
unfold prefixLen
have hgo : ∀ n, prefixLenAux P (P.take q) n = 0 ∨
suffixTest (P.take (prefixLenAux P (P.take q) n)) (P.take q) = true := by
intro n
induction n with
| zero => left; simp [prefixLenAux]
| succ n ih =>
by_cases h : suffixTest (P.take (n + 1)) (P.take q)
· right; try 'simp' instead of 'simpa'
Note: This linter can be disabled with `set_option linter.unnecessarySimpa false`simpa [prefixLenAux, h] using h
· simpa [prefixLenAux, h] using ih
rcases hgo (q - 1) with hzero | hsuf
· rw [hzero]; exact isSuffix_empty _
· exact (suffixTest_eq_isSuffix _ _).mp hsuf
π(q) is maximal among proper prefixes of P that are suffixes of
P.take q.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`Try `simp at ht` instead of `simpa using ht`
Note: This linter can be disabled with `set_option linter.unnecessarySimpa false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixLen_maximal`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`theorem prefixLen_maximal (P : Text α) (q k : ℕ) (hk : k < q)
(hsuf : isSuffix (P.take k) (P.take q)) : k ≤ prefixLen P q := by
unfold prefixLen
have ht : suffixTest (P.take k) (P.take q) = true := (suffixTest_eq_isSuffix _ _).mpr hsuf
have hgo : ∀ n, k ≤ n → k ≤ prefixLenAux P (P.take q) n := by
intro n hkn
induction n with
| zero => omega
| succ n ih =>
by_cases hts : suffixTest (P.take (n + 1)) (P.take q)
· simp [prefixLenAux, hts]; omega
· have hklt : k < n + 1 := by
by_cases hk_eq : k = n + 1
· subst k; Try `simp at ht` instead of `simpa using ht`
Note: This linter can be disabled with `set_option linter.unnecessarySimpa false`simpa [hts] using ht
· omega
have := ih (by omega)
simpa [prefixLenAux, hts] using this
have hle : k ≤ q - 1 := by omega
exact hgo (q - 1) hle
Follow failure links from k: repeatedly replace k by π[k-1] while
k > 0 and P[k] ≠ c, returning the first k (along the chain) with
P[k] = c, or 0. hinv guarantees every π[i] < i + 1, so the chain
strictly decreases.
def failureFollow (P : Text α) (π : List ℕ) (c : α) (k : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1) : ℕ :=
if hk : k = 0 then 0
else if (P.getD k default) = c then k
else failureFollow P π c (π.getD (k - 1) 0) hinv
termination_by k
decreasing_by
simp_wf
have hpos : 0 < k := Nat.pos_of_ne_zero hk
have hk' : (k - 1) + 1 = k := by omega
simpa [hk'] using hinv (k - 1)
failureFollow never increases its argument.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma failureFollow_le (P : Text α) (π : List ℕ) (c : α) (k : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1) : failureFollow P π c k hinv ≤ k := by
rw [failureFollow.eq_1]
by_cases hk : k = 0
· simp [hk]
· simp [hk]
by_cases hc : P[k]?.getD default = c
· simp [hc]
· simp [hc]
have ih := failureFollow_le P π c (π.getD (k - 1) 0) hinv
have hlt : π.getD (k - 1) 0 < k := by
have hpos : 0 < k := Nat.pos_of_ne_zero hk
have h := hinv (k - 1)
omega
exact le_of_lt (lt_of_le_of_lt ih hlt)
termination_by k
decreasing_by
simp_wf
have hpos : 0 < k := Nat.pos_of_ne_zero hk
have hk' : (k - 1) + 1 = k := by omega
simpa [hk'] using hinv (k - 1)
The executable COMPUTE-PREFIX-FUNCTION (CLRS §32.4). π is the prefix
array computed so far (length q), k = π[q-1], and hinv records that every
π[i] < i + 1; hk_lt records k < π.length.
def computePrefixGo (P : Text α) (π : List ℕ) (k : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1) (hk_lt : k < π.length) : Text α → List ℕ
| [] => π
| c :: rest =>
let k' := failureFollow P π c k hinv
let k'' := if (P.getD k' default) = c then k' + 1 else 0
have hk'le : k' ≤ k := failureFollow_le P π c k hinv
have hk'lt : k' < π.length := lt_of_le_of_lt hk'le hk_lt
have hk''le : k'' ≤ π.length := by
unfold k''
split <;> omega
have hinv' : ∀ i, (π ++ [k'']).getD i 0 < i + 1 := by
intro i
by_cases hi : i < π.length
· rw [List.getD_append π [k''] 0 i hi]
exact hinv i
· have hge : π.length ≤ i := by omega
rw [List.getD_append_right π [k''] 0 i hge]
have hle : [k''].getD (i - π.length) 0 ≤ k'' := by
by_cases h : i - π.length = 0 <;> simp [List.getD, h]
omega
have hk''lt : k'' < (π ++ [k'']).length := by
simp [hk''le]
computePrefixGo P (π ++ [k'']) k'' hinv' hk''lt rest
The executable prefix-function array: (computePrefixFunction P)[q] is the
prefix function π(q) (CLRS §32.4).
def computePrefixFunction (P : Text α) : List ℕ :=
match P with
| [] => []
| a :: as => computePrefixGo P [0] 0 (by intro i; simp) (by simp) as
If k < π(q) and P.take k is a suffix of P.take q, then P.take k is
also a suffix of P.take (π q) (CLRS Lemma 32.5, induction step).
Search for the largest k ≤ n such that P.take k is a suffix of P.take q
and P[k] = c.
def prefixMatchAux (P : Text α) (q : ℕ) (c : α) : ℕ → ℕ
| 0 => 0
| n + 1 =>
if suffixTest (P.take (n + 1)) (P.take q) && (P.getD (n + 1) default == c) then n + 1
else prefixMatchAux P q c n
One plus the largest k < q such that P.take k is a suffix of P.take q
and P[k] = c, or 0 when no such k exists.
def prefixMatch (P : Text α) (q : ℕ) (c : α) : ℕ :=
let k := prefixMatchAux P q c (q - 1)
if suffixTest (P.take k) (P.take q) && (P.getD k default == c) then k + 1 else 0
prefixMatchAux never exceeds its bound.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_le`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma prefixMatchAux_le (P : Text α) (q : ℕ) (c : α) (n : ℕ) : prefixMatchAux P q c n ≤ n := by
induction n with
| zero => simp [prefixMatchAux]
| succ n ih =>
unfold prefixMatchAux
split <;> omega
If prefixMatchAux returns a nonzero value, that value's character matches c.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_char`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_char`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_char`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_char`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_char`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_char`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_char`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_char`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_char`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_char`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_char`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_char`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_char`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_char`:
[DecidableEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma prefixMatchAux_char (P : Text α) (q : ℕ) (c : α) (n : ℕ) :
prefixMatchAux P q c n = 0 ∨ (P.getD (prefixMatchAux P q c n) default == c) = true := by
induction n with
| zero => simp [prefixMatchAux]
| succ n ih =>
unfold prefixMatchAux
split
· next h => right; exact (Bool.and_eq_true_iff.mp h).2
· next _ => exact ih
prefixMatchAux is maximal: any candidate below the bound is at most its result.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_maximal`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma prefixMatchAux_maximal (P : Text α) (q : ℕ) (c : α) (n k : ℕ) (hk : k ≤ n)
(hsuf : suffixTest (P.take k) (P.take q) = true) (hchar : (P.getD k default == c) = true) :
k ≤ prefixMatchAux P q c n := by
induction n with
| zero => omega
| succ n ih =>
unfold prefixMatchAux
split
· next _ => omega
· next hnot =>
have hkne : k ≠ n + 1 := by
intro hkk
apply hnot
subst k
rw [hsuf, hchar]
rfl
have hklt : k ≤ n := by omega
exact ih hklt
If a candidate exists below the bound, the result of prefixMatchAux is itself a
candidate (its character matches c).
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_found`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma prefixMatchAux_found (P : Text α) (q : ℕ) (c : α) (n : ℕ)
(hex : ∃ j, j ≤ n ∧ (suffixTest (P.take j) (P.take q) && (P.getD j default == c)) = true) :
(P.getD (prefixMatchAux P q c n) default == c) = true := by
induction n with
| zero =>
rcases hex with ⟨j, hj, hjprop⟩
have hj0 : j = 0 := by omega
change (P.getD 0 default == c) = true
rw [hj0] at hjprop
exact (Bool.and_eq_true_iff.mp hjprop).2
| succ n ih =>
unfold prefixMatchAux
by_cases ht : (suffixTest (P.take (n+1)) (P.take q) && (P.getD (n+1) default == c)) = true
· rw [ht]
exact (Bool.and_eq_true_iff.mp ht).2
· have htf : (suffixTest (P.take (n+1)) (P.take q) && (P.getD (n+1) default == c)) = false := by
cases hh : (suffixTest (P.take (n+1)) (P.take q) && (P.getD (n+1) default == c))
· rfl
· exact (ht hh).elim
rw [htf]
rcases hex with ⟨j, hj, hjprop⟩
have hjne : j ≠ n + 1 := by
intro hjj
rw [hjj] at hjprop
exact (ht hjprop).elim
have hjle : j ≤ n := by omega
exact ih ⟨j, hjle, hjprop⟩
The empty prefix P.take 0 = [] is always a suffix of P.take q.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_take_zero`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_take_zero`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.suffixTest_take_zero`:
[Inhabited α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [Inhabited α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma suffixTest_take_zero (P : Text α) (q : ℕ) :
suffixTest (P.take 0) (P.take q) = true := by
exact (suffixTest_eq_isSuffix (P.take 0) (P.take q)).mpr (isSuffix_empty _)
prefixMatchAux always returns a value whose prefix is a suffix of P.take q.
If P.take r is a suffix of P.take q ++ [a] with 0 < r ≤ P.length, then
the character P[r-1] equals a.
lemma suffix_snoc_char_eq (P : Text α) (q r : ℕ) (a : α) (hrpos : 0 < r) (hrle : r ≤ P.length)
(hsuf : isSuffix (P.take r) (P.take q ++ [a])) : P.getD (r - 1) default = a := by
have hchar : (P.take r).getLast? = some a := suffix_last_char_of_snoc P (P.take q) r a hsuf hrpos hrle
have htake : P.take r = P.take (r - 1) ++ [a] := take_eq_take_pred_append P r a hrpos hrle hchar
have hlenr : (P.take r).length = r := by rw [List.length_take]; exact Nat.min_eq_left hrle
have hlt : r - 1 < (P.take r).length := by rw [hlenr]; omega
have hltP : r - 1 < P.length := by omega
have h1 : (P.take r).getD (r - 1) default = P.getD (r - 1) default := by
rw [List.getD_eq_getElem (P.take r) default hlt]
rw [List.getElem_take]
rw [← List.getD_eq_getElem P default hltP]
have h2 : (P.take (r - 1) ++ [a]).getD (r - 1) default = a := by
have hlen : (P.take (r - 1)).length = r - 1 := by
rw [List.length_take]
exact Nat.min_eq_left (by omega)
rw [List.getD_append_right (P.take (r - 1)) [a] default (r - 1) (by omega)]
simp [hlen]
calc
P.getD (r - 1) default = (P.take r).getD (r - 1) default := h1.symm
_ = (P.take (r - 1) ++ [a]).getD (r - 1) default := by rw [htake]
_ = a := h2
prefixMatch P q c equals k + 1 when the search result's character matches
c, and 0 otherwise.
The recurrence (CLRS Lemma 32.6): π(q + 1) extends the longest proper
prefix-suffix of P.take q whose next character matches P[q].
`List.take_succ` has been deprecated: Use `List.take_add_one` instead`List.take_succ` has been deprecated: Use `List.take_add_one` instead
theorem prefixLen_snoc_eq (P : Text α) (q : ℕ) (hqpos : 0 < q) (hq : q < P.length) :
prefixLen P (q + 1) = prefixMatch P q (P.getD q default) := by
have hqlen : q + 1 ≤ P.length := Nat.succ_le_of_lt hq
have htake : P.take (q + 1) = P.take q ++ [P.getD q default] := by
rw [`List.take_succ` has been deprecated: Use `List.take_add_one` insteadList.take_succ]
congr 1
rw [List.getD_eq_getElem P default (by omega : q < P.length)]
simp
let c := P.getD q default
let k := prefixMatchAux P q c (q - 1)
have hksuf : suffixTest (P.take k) (P.take q) = true := by
dsimp [k]
exact prefixMatchAux_satisfies P q c (q - 1)
have hkle : k ≤ q - 1 := by
dsimp [k]
exact prefixMatchAux_le P q c (q - 1)
have hklt : k < q := by omega
have hkltP : k < P.length := by omega
have hle : prefixLen P (q + 1) ≤ prefixMatch P q c := by
by_cases h0 : prefixLen P (q + 1) = 0
· rw [h0]
exact Nat.zero_le _
· let r := prefixLen P (q + 1)
have hrpos : 0 < r := Nat.pos_of_ne_zero h0
have hrle : r ≤ P.length := le_trans (prefixLen_le P (q + 1)) hqlen
have hrle' : r ≤ q := by
have hlt := prefixLen_lt_of_pos P (q + 1) (by omega)
dsimp [r]
omega
have hsat := prefixLen_satisfies P (q + 1)
rw [htake] at hsat
have hpre : isSuffix (P.take (r - 1)) (P.take q) :=
suffix_dropLast_of_snoc P (P.take q) r c hrpos hrle hsat
have hlastchar : P.getD (r - 1) default = c :=
suffix_snoc_char_eq P q r c hrpos hrle hsat
have hsuf' : suffixTest (P.take (r - 1)) (P.take q) = true :=
(suffixTest_eq_isSuffix _ _).mpr hpre
have hchar' : (P.getD (r - 1) default == c) = true := beq_iff_eq.mpr hlastchar
have hcand : (suffixTest (P.take (r - 1)) (P.take q) && (P.getD (r - 1) default == c)) = true := by
rw [hsuf', hchar']
rfl
have hmax : r - 1 ≤ k :=
prefixMatchAux_maximal P q c (q - 1) (r - 1) (by omega) hsuf' hchar'
have hchar_k : (P.getD k default == c) = true :=
prefixMatchAux_found P q c (q - 1) ⟨r - 1, by omega, hcand⟩
have hpm : prefixMatch P q c = k + 1 := by
rw [prefixMatch_eq]
dsimp [k] at hchar_k
rw [hchar_k]
rfl
rw [hpm]
omega
have hge : prefixMatch P q c ≤ prefixLen P (q + 1) := by
by_cases hck : (P.getD k default == c) = true
· have hchar : P.getD k default = c := beq_iff_eq.mp hck
have hksuf' : isSuffix (P.take k) (P.take q) := (suffixTest_eq_isSuffix _ _).mp hksuf
have htakek : P.take (k + 1) = P.take k ++ [P.getD k default] := by
rw [`List.take_succ` has been deprecated: Use `List.take_add_one` insteadList.take_succ]
congr 1
rw [List.getD_eq_getElem P default (by omega : k < P.length)]
simp
have hsufk1 : isSuffix (P.take (k + 1)) (P.take (q + 1)) := by
rw [htakek, htake]
have hchar' : P.getD k default = P.getD q default := by
dsimp [c] at hchar
exact hchar
have hsuf0 : isSuffix (P.take k ++ [P.getD k default]) (P.take q ++ [P.getD k default]) :=
suffix_append_right hksuf'
rw [← hchar']
exact hsuf0
have hklt1 : k + 1 < q + 1 := by omega
have hk1 : k + 1 ≤ prefixLen P (q + 1) :=
prefixLen_maximal P (q + 1) (k + 1) hklt1 hsufk1
have hpm : prefixMatch P q c = k + 1 := by
rw [prefixMatch_eq]
dsimp [k] at hck
rw [hck]
rfl
rw [hpm]
exact hk1
· have hpm : prefixMatch P q c = 0 := by
rw [prefixMatch_eq]
have hf : (P.getD (prefixMatchAux P q c (q - 1)) default == c) = false := by
dsimp [k] at hck
cases hh : (P.getD (prefixMatchAux P q c (q - 1)) default == c)
· rfl
· exact (hck hh).elim
rw [hf]
rfl
rw [hpm]
exact Nat.zero_le _
exact le_antisymm hle hge
When P.take (n+1) is not a suffix of P.take q, prefixMatchAux at n+1
falls through to n.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_succ_of_not_suffix`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_succ_of_not_suffix`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_succ_of_not_suffix`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma prefixMatchAux_succ_of_not_suffix (P : Text α) (q : ℕ) (c : α) (n : ℕ)
(h : suffixTest (P.take (n + 1)) (P.take q) = false) :
prefixMatchAux P q c (n + 1) = prefixMatchAux P q c n := by
simp [prefixMatchAux, h]
If no value in (n', n] is a suffix of P.take q, the search from n
agrees with the search from n'.
lemma prefixMatchAux_drop (P : Text α) (q : ℕ) (c : α) (n n' : ℕ) (hle : n' ≤ n)
(h : ∀ j, n' < j → j ≤ n → suffixTest (P.take j) (P.take q) = false) :
prefixMatchAux P q c n = prefixMatchAux P q c n' := by
induction n generalizing n' with
| zero =>
have hn' : n' = 0 := by omega
subst n'
rfl
| succ n ih =>
by_cases hn' : n' = n + 1
· subst n'; rfl
· have hn'le : n' ≤ n := by omega
have hsuf : suffixTest (P.take (n + 1)) (P.take q) = false :=
h (n + 1) (by omega) (by omega)
rw [prefixMatchAux_succ_of_not_suffix P q c n hsuf]
exact ih n' hn'le (fun j hj1 hj2 => h j hj1 (by omega))
prefixMatchAux is insensitive to the suffix target q, provided the
suffix tests agree on every position up to the bound.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.prefixMatchAux_congr`:
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma prefixMatchAux_congr (P : Text α) (q q' : ℕ) (c : α) (n : ℕ)
(h : ∀ j, j ≤ n → (suffixTest (P.take j) (P.take q) = true ↔ suffixTest (P.take j) (P.take q') = true)) :
prefixMatchAux P q c n = prefixMatchAux P q' c n := by
induction n with
| zero => rfl
| succ n ih =>
have hsuf : suffixTest (P.take (n + 1)) (P.take q) = suffixTest (P.take (n + 1)) (P.take q') := by
have hiff := h (n + 1) (by omega)
revert hiff
generalize hq : suffixTest (P.take (n + 1)) (P.take q) = b1
generalize hq' : suffixTest (P.take (n + 1)) (P.take q') = b2
intro hiff
cases b1 <;> cases b2 <;> simp_all
have ih' : prefixMatchAux P q c n = prefixMatchAux P q' c n :=
ih (fun j hj => h j (by omega))
rw [prefixMatchAux, prefixMatchAux]
rw [hsuf]
rw [ih']
The from-scratch search from k - 1 over P.take q agrees with the search from
prefixLen P k over P.take k, when k = prefixLen P q (the failure-link jump).
Following failure links from k = π(q) agrees with the from-scratch search
prefixMatchAux P q c k, when π is the correct prefix-function array.
lemma failureFollow_eq_prefixMatchAux (P : Text α) (π : List ℕ) (c : α) (q k : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1)
(hπ : ∀ i, i < q → π.getD i 0 = prefixLen P (i + 1))
(hk : k = prefixLen P q) :
failureFollow P π c k hinv = prefixMatchAux P q c k := by
revert q
refine Nat.strong_induction_on k ?_
intro k ih q hπ hk
by_cases hk0 : k = 0
· subst hk0
rw [failureFollow.eq_1, prefixMatchAux]
rfl
· have hkpos : 0 < k := Nat.pos_of_ne_zero hk0
have hsuf : suffixTest (P.take k) (P.take q) = true := by
simpa [hk] using (suffixTest_eq_isSuffix _ _).mpr (prefixLen_satisfies P q)
obtain ⟨n, rfl⟩ := Nat.exists_eq_succ_of_ne_zero hk0
have hqpos : 0 < q := by
have hle := prefixLen_le P q
rw [← hk] at hle
omega
have hnltq : n < q := by
have hlt := prefixLen_lt_of_pos P q hqpos
rw [← hk] at hlt
omega
rw [failureFollow.eq_1]
simp only [Nat.succ_ne_zero, This simp argument is unused:
if_false
Hint: Omit it from the simp argument list.
simp only [Nat.succ_ne_zero,̵ ̵i̵f̵_̵f̵a̵l̵s̵e̵]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`if_false]
rw [prefixMatchAux]
rw [hsuf]
change (if P.getD (n + 1) default = c then n + 1 else failureFollow P π c (π.getD n 0) hinv)
= (if (P.getD (n + 1) default == c) = true then n + 1 else prefixMatchAux P q c n)
by_cases hc : P.getD (n + 1) default = c
· rw [if_pos hc, if_pos (beq_iff_eq.mpr hc)]
· have hcneg : ¬ (P.getD (n + 1) default == c) = true := by
intro hh
exact hc (beq_iff_eq.mp hh)
rw [if_neg hc, if_neg hcneg]
have hπn : π.getD n 0 = prefixLen P (n + 1) := hπ n hnltq
rw [hπn]
have hih := ih (prefixLen P (n + 1)) (prefixLen_lt_of_pos P (n + 1) (by omega))
(n + 1) (fun i hi => hπ i (by omega)) rfl
rw [hih]
exact (prefixMatchAux_chain_jump P q (n + 1) c (by simpa [hk]) (by omega)).symm
prefixMatchAux from prefixLen P q agrees with the full search from q - 1.
One step of computePrefixGo computes prefixLen P (π.length + 1) (the
failure-link recurrence, CLRS Lemma 32.6).
failureFollow's result is independent of its hinv proof argument.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_irrelevant`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_irrelevant`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_irrelevant`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_irrelevant`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_irrelevant`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_irrelevant`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma failureFollow_irrelevant (P : Text α) (π : List ℕ) (c : α) (k : ℕ)
(hinv hinv' : ∀ i, π.getD i 0 < i + 1) :
failureFollow P π c k hinv = failureFollow P π c k hinv' := by
unfold failureFollow
by_cases hk : k = 0 <;> simp [hk]
computePrefixGo's result is independent of its hinv/hk_lt proof arguments.
lemma computePrefixGo_irrelevant (P : Text α) (π : List ℕ) (k : ℕ) (rest : Text α)
(hinv hinv' : ∀ i, π.getD i 0 < i + 1) (hk_lt hk_lt' : k < π.length) :
computePrefixGo P π k hinv hk_lt rest = computePrefixGo P π k hinv' hk_lt' rest := by
induction rest generalizing π k hinv hinv' hk_lt hk_lt' with
| nil => rfl
| cons c rest' ih =>
unfold computePrefixGo
simp [This simp argument is unused:
failureFollow_irrelevant
Hint: Omit it from the simp argument list.
s̵i̵m̵p̵ ̵[̵f̵a̵i̵l̵u̵r̵e̵F̵o̵l̵l̵o̵w̵_̵i̵r̵r̵e̵l̵e̵v̵a̵n̵t̵,̵ ̵i̵h̵]̵s̲i̲m̲p̲ ̲[̲i̲h̲]̲
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`failureFollow_irrelevant, This simp argument is unused:
ih
Hint: Omit it from the simp argument list.
simp [failureFollow_irrelevant,̵ ̵i̵h̵]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`ih]
Extract the head/tail of P.drop n = c :: rest.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.drop_cons`:
[BEq α]
[DecidableEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [DecidableEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma drop_cons (P : Text α) (n : ℕ) (c : α) (rest : Text α) (h : P.drop n = c :: rest) :
n < P.length ∧ c = P.getD n default ∧ rest = P.drop (n + 1) := by
have hlen : n < P.length := by
by_contra hge
have hnil : P.drop n = [] := List.drop_eq_nil_of_le (by omega)
rw [h] at hnil
cases hnil
refine ⟨hlen, ?_, ?_⟩
· have hhead : (P.drop n).head? = (c :: rest).head? := by rw [h]
simp at hhead
have : P.getD n default = c := by
change P[n]?.getD default = c
rw [hhead]
rfl
exact this.symm
· have htail : (P.drop n).drop 1 = (c :: rest).drop 1 := by rw [h]
simp at htail
exact htail.symm
The invariant of computePrefixGo: it extends a correct prefix array.
lemma computePrefixGo_correct (P : Text α) (π : List ℕ) (k : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1) (hk_lt : k < π.length)
(hπ : ∀ i, i < π.length → π.getD i 0 = prefixLen P (i + 1))
(hk : k = prefixLen P π.length) :
∀ rest, rest = P.drop π.length →
∀ i, i < (computePrefixGo P π k hinv hk_lt rest).length →
(computePrefixGo P π k hinv hk_lt rest).getD i 0 = prefixLen P (i + 1) := by
intro rest hrest
induction rest generalizing π k hinv hk_lt hπ hk with
| nil =>
intro i hi
simpa [computePrefixGo] using hπ i (by simpa [computePrefixGo] using hi)
| cons c rest' ih =>
intro i hi
have hd := drop_cons P π.length c rest' hrest.symm
have hqlt : π.length < P.length := hd.1
have hc : c = P.getD π.length default := hd.2.1
have hrest' : rest' = P.drop (π.length + 1) := hd.2.2
have hqpos : 0 < π.length := by omega
let k' := failureFollow P π c k hinv
let k'' := if (P.getD k' default) = c then k' + 1 else 0
have hk'le : k' ≤ k := failureFollow_le P π c k hinv
have hk''le : k'' ≤ π.length := by
dsimp [k'']
have hk'lt : k' < π.length := lt_of_le_of_lt hk'le hk_lt
split <;> omega
have hstep : k'' = prefixLen P (π.length + 1) := by
dsimp [k'', k']
exact computePrefixGo_step P π k c hinv hπ hk hc hqpos hqlt
have hπ' : ∀ j, j < (π ++ [k'']).length → (π ++ [k'']).getD j 0 = prefixLen P (j + 1) := by
intro j hj
by_cases hjπ : j < π.length
· rw [List.getD_append π [k''] 0 j hjπ]
exact hπ j hjπ
· have hge : π.length ≤ j := by omega
rw [List.getD_append_right π [k''] 0 j hge]
have hj_eq : j = π.length := by
have hj' : j < π.length + 1 := by simpa [List.length_append] using hj
omega
subst j
simpa using hstep
have hk' : k'' = prefixLen P (π ++ [k'']).length := by
simpa [List.length_append] using hstep
have hinv'' : ∀ j, (π ++ [k'']).getD j 0 < j + 1 := by
intro j
by_cases hjπ : j < π.length
· rw [List.getD_append π [k''] 0 j hjπ]
exact hinv j
· have hge : π.length ≤ j := by omega
rw [List.getD_append_right π [k''] 0 j hge]
have hle : [k''].getD (j - π.length) 0 ≤ k'' := by
by_cases h : j - π.length = 0 <;> simp [List.getD, h]
omega
have hk''lt : k'' < (π ++ [k'']).length := by
simp [hk''le]
have heq : computePrefixGo P π k hinv hk_lt (c :: rest') =
computePrefixGo P (π ++ [k'']) k'' hinv'' hk''lt rest' := by
rw [computePrefixGo]
rw [heq] at hi ⊢
exact (ih (π ++ [k'']) k'' hinv'' hk''lt hπ' hk' (by simpa [List.length_append] using hrest')) i hi
computePrefixGo's result has length π.length + rest.length.
lemma computePrefixGo_length (P : Text α) (π : List ℕ) (k : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1) (hk_lt : k < π.length) (rest : Text α) :
(computePrefixGo P π k hinv hk_lt rest).length = π.length + rest.length := by
induction rest generalizing π k hinv hk_lt with
| nil => rfl
| cons c rest' ih =>
rw [computePrefixGo]
rw [ih]
simp
omega
The executable COMPUTE-PREFIX-FUNCTION array equals the prefix function
prefixLen (CLRS Lemma 32.6).
The executable prefix array has exactly |P| entries.
Every entry of the executable prefix array is strictly below its successor
index, so it can serve as the hinv termination argument of failureFollow.
The advance step of the KMP scan: if the current fallback position's
character matches a, extend the match by one; otherwise restart at 0.
failureFollow guarantees its result is 0 whenever its character does not
match a, so the else 0 branch is exactly the textbook q ← q state.
def kmpAdvance (P : Text α) (q' : ℕ) (a : α) : ℕ :=
if P.getD q' default = a then q' + 1 else 0
One KMP scan step (CLRS KMP-MATCHER lines 6-9): given the current state
q (the number of matched characters, q ≤ |P|) and the next text character
a, follow failure links until the next character matches, then advance. When
q = |P| the step first falls back to π[|P|-1], which is the textbook reset
q ← π[q] performed before the next character is read.
The Knuth–Morris–Pratt scan: scan T left-to-right maintaining the
automaton state q = δ*(0, scanned), recording every shift where the state
reaches |P|. scanned is the text already scanned and m = |P|.
def kmpScan (P : Text α) (π : List ℕ) (m : ℕ) (scanned : Text α) (q : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1) : Text α → List ℕ
| [] => if q == m then [scanned.length - m] else []
| c :: rest =>
let q' := kmpStep P π q c hinv
let tail := kmpScan P π m (scanned ++ [c]) q' hinv rest
if q == m then (scanned.length - m) :: tail else tail
The Knuth–Morris–Pratt matcher: the list of all shifts where P occurs in
T, computed by the prefix function plus a single left-to-right scan
(CLRS §32.4).
The specification transition: δ(q, a) written as "extend by one if the
character matches P[q], otherwise the longest proper prefix-suffix extension
prefixMatch". This is the semantic content of one KMP scan step.
def kmpNextSpec (P : Text α) (q : ℕ) (a : α) : ℕ :=
if q < P.length ∧ P.getD q default = a then q + 1 else prefixMatch P q a
kmpAdvance over the from-scratch search result is exactly prefixMatch.
'change
(if P.getD (prefixMatchAux P q a (q - 1)) default = a then prefixMatchAux P q a (q - 1) + 1 else 0) =
(if (P.getD (prefixMatchAux P q a (q - 1)) default == a) = true then prefixMatchAux P q a (q - 1) + 1
else 0)' tactic does nothing
Note: This linter can be disabled with `set_option linter.unusedTactic false`
lemma kmpAdvance_eq_prefixMatch (P : Text α) (q : ℕ) (a : α) :
kmpAdvance P (prefixMatchAux P q a (q - 1)) a = prefixMatch P q a := by
unfold kmpAdvance
rw [prefixMatch_eq P q a]
'change
(if P.getD (prefixMatchAux P q a (q - 1)) default = a then prefixMatchAux P q a (q - 1) + 1 else 0) =
(if (P.getD (prefixMatchAux P q a (q - 1)) default == a) = true then prefixMatchAux P q a (q - 1) + 1
else 0)' tactic does nothing
Note: This linter can be disabled with `set_option linter.unusedTactic false`change (if P.getD (prefixMatchAux P q a (q - 1)) default = a then prefixMatchAux P q a (q - 1) + 1 else 0)
= (if (P.getD (prefixMatchAux P q a (q - 1)) default == a) = true then prefixMatchAux P q a (q - 1) + 1 else 0)
by_cases h : P.getD (prefixMatchAux P q a (q - 1)) default = a
· rw [if_pos h, if_pos (beq_iff_eq.mpr h)]
· rw [if_neg h]
have hneg : ¬ (P.getD (prefixMatchAux P q a (q - 1)) default == a) = true := by
intro hh
exact h (beq_iff_eq.mp hh)
rw [if_neg hneg]
If P[q] = a, the failure-link search starting at q stays at q.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_eq_self_of_char`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma failureFollow_eq_self_of_char (P : Text α) (π : List ℕ) (a : α) (q : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1) (hchar : P.getD q default = a) :
failureFollow P π a q hinv = q := by
rw [failureFollow.eq_1]
by_cases hq0 : q = 0
· simp [hq0]
· simp only [hq0, This simp argument is unused:
if_false
Hint: Omit it from the simp argument list.
simp only [hq0,̵ ̵i̵f̵_̵f̵a̵l̵s̵e̵]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`if_false]
by_cases hc : P[q]?.getD default = a
· simp [hc]
· have hc' : P[q]?.getD default = a := by simpa using hchar
exact (hc hc').elim
One fallback step: when P[q] ≠ a and q > 0, the search moves to
π[q-1].
automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollow_step_eq`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma failureFollow_step_eq (P : Text α) (π : List ℕ) (a : α) (q : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1) (hqpos : 0 < q) (hne : P.getD q default ≠ a) :
failureFollow P π a q hinv = failureFollow P π a (π.getD (q - 1) 0) hinv := by
rw [failureFollow.eq_1]
by_cases hq0 : q = 0
· omega
· simp only [hq0, This simp argument is unused:
if_false
Hint: Omit it from the simp argument list.
simp only [hq0,̵ ̵i̵f̵_̵f̵a̵l̵s̵e̵]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`if_false]
by_cases hc : P[q]?.getD default = a
· have hc' : P[q]?.getD default = a := by simpa using hc
have hne' : P[q]?.getD default ≠ a := by simpa using hne
exact (hne' hc').elim
· simp [hc]
The failure-link search from prefixLen P q agrees with the from-scratch
search prefixMatchAux P q a (q - 1).
When P[q] ≠ a, the failure-link search from q agrees with the
from-scratch search prefixMatchAux P q a (q - 1) (for q = 0 both are 0).
suffixLen P (P.take q ++ [a]) ≤ kmpNextSpec P q a: the suffix function of
a one-step extension never exceeds the specification transition.
`List.take_succ` has been deprecated: Use `List.take_add_one` instead
lemma suffixLen_snoc_le_spec (P : Text α) (q : ℕ) (a : α) (Variable name `hq` is not explicitly referenced.
The binding can be removed (if unused) or named `_` (if used implicitly).
Note: This linter can be disabled with `set_option linter.unusedVariables false`hq : q ≤ P.length) :
suffixLen P (P.take q ++ [a]) ≤ kmpNextSpec P q a := by
unfold kmpNextSpec
by_cases hcond : q < P.length ∧ P.getD q default = a
· rw [if_pos hcond]
have hle := suffixLen_le_length P (P.take q ++ [a])
have hlen : (P.take q ++ [a]).length ≤ q + 1 := by
rw [List.length_append, List.length_singleton, List.length_take]
exact Nat.add_le_add_right (Nat.min_le_left q P.length) 1
omega
· rw [if_neg hcond]
have hr : suffixLen P (P.take q ++ [a]) ≤ P.length := suffixLen_le P (P.take q ++ [a])
have hrle : suffixLen P (P.take q ++ [a]) ≤ q + 1 := by
have hle := suffixLen_le_length P (P.take q ++ [a])
have hlen : (P.take q ++ [a]).length ≤ q + 1 := by
rw [List.length_append, List.length_singleton, List.length_take]
exact Nat.add_le_add_right (Nat.min_le_left q P.length) 1
omega
have hsuf : isSuffix (P.take (suffixLen P (P.take q ++ [a]))) (P.take q ++ [a]) :=
suffixLen_satisfies P (P.take q ++ [a])
set r := suffixLen P (P.take q ++ [a]) with hr_def
have hr' : r ≤ P.length := by simpa [hr_def] using hr
have hrle' : r ≤ q + 1 := by simpa [hr_def] using hrle
have hsuf' : isSuffix (P.take r) (P.take q ++ [a]) := by simpa [hr_def] using hsuf
by_cases hrq : r = q + 1
· exfalso
have hqlt : q < P.length := by
have : q + 1 ≤ P.length := by simpa [hrq] using hr'
omega
have hchar : P.getD q default = a := by
have hsuf'' : isSuffix (P.take (q + 1)) (P.take q ++ [a]) := by simpa [hrq] using hsuf'
have hk' : q + 1 ≤ P.length := by omega
have hlast : (P.take (q + 1)).getLast? = some a :=
suffix_last_char_of_snoc P (P.take q) (q + 1) a hsuf'' (by omega) hk'
have htake1 : P.take (q + 1) = P.take q ++ [a] :=
take_eq_take_pred_append P (q + 1) a (by omega) hk' hlast
have htake2 : P.take (q + 1) = P.take q ++ [P.getD q default] := by
rw [`List.take_succ` has been deprecated: Use `List.take_add_one` insteadList.take_succ]
congr 1
rw [List.getD_eq_getElem P default (by omega : q < P.length)]
simp
have hconcat : P.take q ++ [a] = P.take q ++ [P.getD q default] := by
rw [← htake1, ← htake2]
have hsing : [a] = [P.getD q default] := by
simpa [List.drop_left] using (congrArg (fun t => t.drop (P.take q).length) hconcat)
exact (List.cons.inj hsing).1.symm
exact hcond ⟨hqlt, hchar⟩
· have hrq' : r ≤ q := by omega
by_cases hr0 : r = 0
· rw [hr0]
exact Nat.zero_le _
· have hrpos : 0 < r := Nat.pos_of_ne_zero hr0
have hpre : isSuffix (P.take (r - 1)) (P.take q) :=
suffix_dropLast_of_snoc P (P.take q) r a hrpos hr' hsuf'
have hchar : P.getD (r - 1) default = a :=
suffix_snoc_char_eq P q r a hrpos hr' hsuf'
have hsuf_t : suffixTest (P.take (r - 1)) (P.take q) = true :=
(suffixTest_eq_isSuffix _ _).mpr hpre
have hchar_t : (P.getD (r - 1) default == a) = true := beq_iff_eq.mpr hchar
have hcand : (suffixTest (P.take (r - 1)) (P.take q) && (P.getD (r - 1) default == a)) = true := by
rw [hsuf_t, hchar_t]
rfl
have hmax : r - 1 ≤ prefixMatchAux P q a (q - 1) :=
prefixMatchAux_maximal P q a (q - 1) (r - 1) (by omega) hsuf_t hchar_t
have hchar_k : (P.getD (prefixMatchAux P q a (q - 1)) default == a) = true :=
prefixMatchAux_found P q a (q - 1) ⟨r - 1, by omega, hcand⟩
have hpm : prefixMatch P q a = prefixMatchAux P q a (q - 1) + 1 := by
rw [prefixMatch_eq]
rw [hchar_k]
rfl
rw [hpm]
omega
kmpNextSpec P q a ≤ suffixLen P (P.take q ++ [a]): the specification
transition never exceeds the suffix function.
`List.take_succ` has been deprecated: Use `List.take_add_one` instead`List.take_succ` has been deprecated: Use `List.take_add_one` instead
lemma spec_le_suffixLen_snoc (P : Text α) (q : ℕ) (a : α) (hP : 0 < P.length) (hq : q ≤ P.length) :
kmpNextSpec P q a ≤ suffixLen P (P.take q ++ [a]) := by
unfold kmpNextSpec
by_cases hcond : q < P.length ∧ P.getD q default = a
· rw [if_pos hcond]
rcases hcond with ⟨hqlt, hchar⟩
have htake0 : P.take (q + 1) = P.take q ++ [P.getD q default] := by
rw [`List.take_succ` has been deprecated: Use `List.take_add_one` insteadList.take_succ]
congr 1
rw [List.getD_eq_getElem P default (by omega : q < P.length)]
simp
have htake : P.take (q + 1) = P.take q ++ [a] := by
rw [htake0, hchar]
have hsuf : isSuffix (P.take (q + 1)) (P.take q ++ [a]) := by
rw [htake]
exact isSuffix_self _
have hk : q + 1 ≤ P.length := by omega
exact suffixLen_maximal P (P.take q ++ [a]) (q + 1) hk hsuf
· rw [if_neg hcond]
by_cases h0 : prefixMatch P q a = 0
· rw [h0]
exact Nat.zero_le _
· have hkchar : (P.getD (prefixMatchAux P q a (q - 1)) default == a) = true := by
by_contra hneg
have hf : (P.getD (prefixMatchAux P q a (q - 1)) default == a) = false := by
cases hh : (P.getD (prefixMatchAux P q a (q - 1)) default == a)
· rfl
· exact (hneg hh).elim
have : prefixMatch P q a = 0 := by
rw [prefixMatch_eq]
rw [hf]
rfl
exact h0 this
have hkchar' : P.getD (prefixMatchAux P q a (q - 1)) default = a := beq_iff_eq.mp hkchar
have hksuf : isSuffix (P.take (prefixMatchAux P q a (q - 1))) (P.take q) :=
(suffixTest_eq_isSuffix _ _).mp (prefixMatchAux_satisfies P q a (q - 1))
have hkle : prefixMatchAux P q a (q - 1) ≤ q - 1 := prefixMatchAux_le P q a (q - 1)
have hkltP : prefixMatchAux P q a (q - 1) < P.length := by omega
have htake0 : P.take (prefixMatchAux P q a (q - 1) + 1) = P.take (prefixMatchAux P q a (q - 1)) ++ [P.getD (prefixMatchAux P q a (q - 1)) default] := by
rw [`List.take_succ` has been deprecated: Use `List.take_add_one` insteadList.take_succ]
congr 1
rw [List.getD_eq_getElem P default (by omega : prefixMatchAux P q a (q - 1) < P.length)]
simp
have htake : P.take (prefixMatchAux P q a (q - 1) + 1) = P.take (prefixMatchAux P q a (q - 1)) ++ [a] := by
rw [htake0, hkchar']
have hsuf1 : isSuffix (P.take (prefixMatchAux P q a (q - 1) + 1)) (P.take q ++ [a]) := by
rw [htake]
exact suffix_append_right hksuf
have hk1 : prefixMatchAux P q a (q - 1) + 1 ≤ P.length := by omega
have hle : prefixMatchAux P q a (q - 1) + 1 ≤ suffixLen P (P.take q ++ [a]) :=
suffixLen_maximal P (P.take q ++ [a]) (prefixMatchAux P q a (q - 1) + 1) hk1 hsuf1
have hpm : prefixMatch P q a = prefixMatchAux P q a (q - 1) + 1 := by
rw [prefixMatch_eq]
rw [hkchar]
rfl
rw [hpm]
exact hle
The transition δ(q, a) equals the specification transition: q + 1 when
q < |P| and P[q] = a, and prefixMatch P q a otherwise.
The executable KMP step computes exactly the automaton transition δ.
The KMP scan equation across one consumed character.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.kmpScan_cons`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.kmpScan_cons`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.kmpScan_cons`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.kmpScan_cons`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.kmpScan_cons`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma kmpScan_cons (P : Text α) (π : List ℕ) (m : ℕ) (scanned : Text α) (q : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1) (c : α) (T : Text α) :
kmpScan P π m scanned q hinv (c :: T)
= (if q == m then [scanned.length - m] else [])
++ kmpScan P π m (scanned ++ [c]) (kmpStep P π q c hinv) hinv T := by
by_cases h : q == m <;> simp [kmpScan, h]
The KMP scan agrees with the finite-automaton scan when π is the correct
prefix-function array.
lemma kmpScan_eq_dfaScan (P : Text α) (π : List ℕ) (hP : 0 < P.length)
(hπ : ∀ i, i < P.length → π.getD i 0 = prefixLen P (i + 1))
(hinv : ∀ i, π.getD i 0 < i + 1) :
∀ (T scanned : Text α) (q : ℕ), q ≤ P.length →
kmpScan P π P.length scanned q hinv T = dfaScan P P.length scanned q T := by
intro T scanned q hq
induction T generalizing scanned q with
| nil =>
rfl
| cons c T ih =>
have hstep : kmpStep P π q c hinv = delta P q c := kmpStep_eq_delta P π q c hP hinv hπ hq
have hq' : kmpStep P π q c hinv ≤ P.length := by
rw [hstep]
unfold delta
exact suffixLen_le P (P.take q ++ [c])
rw [kmpScan_cons P π P.length scanned q hinv c T]
rw [dfaScan_cons P P.length scanned q c T]
rw [ih (scanned ++ [c]) (kmpStep P π q c hinv) hq']
rw [hstep]
Correctness of the Knuth–Morris–Pratt matcher. kmpMatcher P T returns
exactly the shifts that naiveMatcher T P returns, for every pattern and text
(CLRS §32.4).
Every shift returned by the KMP matcher is a valid match.
Every valid match is returned by the KMP matcher.
Costed KMP
The functions below instrument the executable KMP operations with an abstract
unit control-step count: one unit per failure-link traversal plus one unit per
character processed. The metric charges the potentially super-constant part of
the algorithm — the while q > 0 ∧ P[q] ≠ c fallback loop — so that a linear
bound on this metric is a real statement about the executable scan. Erasure
theorems (*_result) show the costed functions project to the plain
executables above.
failureFollow paired with the number of failure-link traversals.
def failureFollowWithCost (P : Text α) (π : List ℕ) (c : α) (k : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1) : ℕ × ℕ :=
if hk : k = 0 then (0, 0)
else if (P.getD k default) = c then (k, 0)
else
let r := failureFollowWithCost P π c (π.getD (k - 1) 0) hinv
(r.1, r.2 + 1)
termination_by k
decreasing_by
simp_wf
have hpos : 0 < k := Nat.pos_of_ne_zero hk
have hk' : (k - 1) + 1 = k := by omega
simpa [hk'] using hinv (k - 1)
Erasing the cost recovers failureFollow.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_result`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma failureFollowWithCost_result (P : Text α) (π : List ℕ) (c : α) (k : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1) :
(failureFollowWithCost P π c k hinv).1 = failureFollow P π c k hinv := by
refine Nat.strong_induction_on k ?_
intro k ih
rw [failureFollowWithCost, failureFollow.eq_1]
by_cases hk : k = 0
· simp [hk]
· simp only [hk, This simp argument is unused:
if_false
Hint: Omit it from the simp argument list.
simp only [hk,̵ ̵i̵f̵_̵f̵a̵l̵s̵e̵]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`if_false]
by_cases hc : P[k]?.getD default = c
· simp [hc]
· simp [hc]
exact ih (π[k - 1]?.getD 0) (by
have hpos : 0 < k := Nat.pos_of_ne_zero hk
have h := hinv (k - 1)
have hk' : (k - 1) + 1 = k := by omega
simpa [hk'] using h)
The fallback cost plus the final state never exceeds the initial state.
automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
automatically included section variable(s) unused in theorem `CLRS.Chapter32.failureFollowWithCost_cost_add_le`:
[BEq α]
[LawfulBEq α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [BEq α] [LawfulBEq α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma failureFollowWithCost_cost_add_le (P : Text α) (π : List ℕ) (c : α) (k : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1) :
(failureFollowWithCost P π c k hinv).2 + (failureFollowWithCost P π c k hinv).1 ≤ k := by
refine Nat.strong_induction_on k ?_
intro k ih
rw [failureFollowWithCost]
by_cases hk : k = 0
· simp [hk]
· simp only [hk, This simp argument is unused:
if_false
Hint: Omit it from the simp argument list.
simp only [hk,̵ ̵i̵f̵_̵f̵a̵l̵s̵e̵]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`if_false]
by_cases hc : P[k]?.getD default = c
· simp [hc]
· simp [hc]
have hlt : π[k - 1]?.getD 0 < k := by
have hpos : 0 < k := Nat.pos_of_ne_zero hk
have h := hinv (k - 1)
have hk' : (k - 1) + 1 = k := by omega
simpa [hk'] using h
have hih := ih (π[k - 1]?.getD 0) hlt
omega
computePrefixGo paired with its unit cost and the final failure state.
def computePrefixGoWithCost (P : Text α) (π : List ℕ) (k : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1) (hk_lt : k < π.length) : Text α → List ℕ × ℕ × ℕ
| [] => (π, 0, k)
| c :: rest =>
let k' := (failureFollowWithCost P π c k hinv).1
let cf := (failureFollowWithCost P π c k hinv).2
let k'' := if (P.getD k' default) = c then k' + 1 else 0
have hk'le : k' ≤ k := by
have hcost := failureFollowWithCost_cost_add_le P π c k hinv
omega
have hk'lt : k' < π.length := lt_of_le_of_lt hk'le hk_lt
have hk''le : k'' ≤ π.length := by
unfold k''
split <;> omega
have hinv' : ∀ i, (π ++ [k'']).getD i 0 < i + 1 := by
intro i
by_cases hi : i < π.length
· rw [List.getD_append π [k''] 0 i hi]
exact hinv i
· have hge : π.length ≤ i := by omega
rw [List.getD_append_right π [k''] 0 i hge]
have hle : [k''].getD (i - π.length) 0 ≤ k'' := by
by_cases h : i - π.length = 0 <;> simp [List.getD, h]
omega
have hk''lt : k'' < (π ++ [k'']).length := by
simp [hk''le]
let r := computePrefixGoWithCost P (π ++ [k'']) k'' hinv' hk''lt rest
(r.1, cf + 1 + r.2.1, r.2.2)
Erasing the cost recovers computePrefixGo.
The amortized potential invariant: cost + final_k ≤ 2 · rest.length + k.
lemma computePrefixGoWithCost_potential (P : Text α) (π : List ℕ) (k : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1) (hk_lt : k < π.length) (rest : Text α) :
(computePrefixGoWithCost P π k hinv hk_lt rest).2.1
+ (computePrefixGoWithCost P π k hinv hk_lt rest).2.2 ≤ 2 * rest.length + k := by
induction rest generalizing π k hinv hk_lt with
| nil => simp [computePrefixGoWithCost]
| cons c rest ih =>
rw [computePrefixGoWithCost]
let k' := (failureFollowWithCost P π c k hinv).1
let cf := (failureFollowWithCost P π c k hinv).2
let k'' := if (P.getD k' default) = c then k' + 1 else 0
have hk'le : k' ≤ k := by
have hcost := failureFollowWithCost_cost_add_le P π c k hinv
omega
have hk'lt : k' < π.length := lt_of_le_of_lt hk'le hk_lt
have hk''le : k'' ≤ π.length := by
unfold k''
split <;> omega
have hinv' : ∀ i, (π ++ [k'']).getD i 0 < i + 1 := by
intro i
by_cases hi : i < π.length
· rw [List.getD_append π [k''] 0 i hi]
exact hinv i
· have hge : π.length ≤ i := by omega
rw [List.getD_append_right π [k''] 0 i hge]
have hle : [k''].getD (i - π.length) 0 ≤ k'' := by
by_cases h : i - π.length = 0 <;> simp [List.getD, h]
omega
have hk''lt : k'' < (π ++ [k'']).length := by
simp [hk''le]
have hcost := failureFollowWithCost_cost_add_le P π c k hinv
have hih := ih (π ++ [k'']) k'' hinv' hk''lt
have hk''le' : k'' ≤ k' + 1 := by
unfold k''
split <;> omega
change cf + 1 + (computePrefixGoWithCost P (π ++ [k'']) k'' hinv' hk''lt rest).2.1
+ (computePrefixGoWithCost P (π ++ [k'']) k'' hinv' hk''lt rest).2.2 ≤ 2 * (rest.length + 1) + k
omega
computePrefixFunction paired with its preprocessing cost.
def computePrefixFunctionWithCost (P : Text α) : List ℕ × ℕ :=
match P with
| [] => ([], 0)
| a :: as =>
let r := computePrefixGoWithCost P [0] 0 (by intro i; simp) (by simp) as
(r.1, r.2.1)
Erasing the cost recovers computePrefixFunction.
The prefix-function construction costs at most 2 · |P| steps.
One KMP scan step paired with its unit cost (one fallback traversal plus
one character).
def kmpStepWithCost (P : Text α) (π : List ℕ) (q : ℕ) (a : α)
(hinv : ∀ i, π.getD i 0 < i + 1) : ℕ × ℕ :=
if q = P.length then
let r := failureFollowWithCost P π a (π.getD (P.length - 1) 0) hinv
(if P.getD r.1 default = a then r.1 + 1 else 0, r.2 + 1)
else
let r := failureFollowWithCost P π a q hinv
(if P.getD r.1 default = a then r.1 + 1 else 0, r.2 + 1)
Erasing the cost recovers kmpStep.
The scan-step cost plus the next state never exceeds q + 2.
The KMP scan paired with its unit cost and the final failure state.
def kmpScanWithCost (P : Text α) (π : List ℕ) (m : ℕ) (scanned : Text α) (q : ℕ)
(hinv : ∀ i, π.getD i 0 < i + 1) : Text α → List ℕ × ℕ × ℕ
| [] => (if q == m then [scanned.length - m] else [], 0, q)
| c :: rest =>
let q' := (kmpStepWithCost P π q c hinv).1
let cstep := (kmpStepWithCost P π q c hinv).2
let r := kmpScanWithCost P π m (scanned ++ [c]) q' hinv rest
(if q == m then (scanned.length - m) :: r.1 else r.1, cstep + r.2.1, r.2.2)
Erasing the cost recovers kmpScan.
The amortized potential invariant of the scan: cost + final_q ≤ 2 · |T| + q.
kmpMatcher paired with its matching-phase cost (the prefix construction
cost is tracked separately by computePrefixFunctionWithCost).
Erasing the cost recovers kmpMatcher.
The matching phase costs at most 2 · |T| + 1 steps.
The total deterministic KMP work: prefix construction plus scan.
KMP total cost. The instrumented prefix construction plus the instrumented
all-occurrences scan costs at most 2·|P| + 2·|T| + 1 control steps, i.e. the
KMP algorithm runs in linear time O(|P| + |T|) (CLRS §32.4).
end Chapter32end CLRS
Imports
32.5. Suffix Arrays
This section formalizes the suffix-array data structure of CLRS §32.5: the
array of starting positions of a text's suffixes sorted into lexicographic
order, together with suffix-array-based pattern search.
A suffix array is a permutation of the positions 0 .. n-1 such that reading
the positions in order lists the suffixes in non-decreasing lexicographic
order. Once the suffixes are sorted, every position at which a pattern p
occurs corresponds to a suffix that begins with p, so a single linear pass
recovers exactly the occurrence set.
Main results:
-
Definition suffixAt: the suffix of a text starting at a given position.
-
Definition suffixLe: the lexicographic order on suffixes, with ties
broken by starting position (a total order, so the construction is
well-defined even when a text has repeated suffixes).
-
Definition SuffixArrayValid: the validity predicate — a permutation of
the positions that is sorted by suffixLe.
-
Definition suffixArray: an executable construction (insertion sort of
the positions by suffixLe).
-
Theorem suffixArray_valid: the construction returns a valid suffix
array.
-
Definition suffixArraySearch: suffix-array-based pattern search.
-
Theorem suffixArraySearch_mem_iff: the search result is sound and
complete — an index i is returned exactly when p is a prefix of
suffixAt t i (i.e. p occurs at position i).
Complexity
The stored suffix positions are 0,...,n-1. For an empty pattern the
range query returns those positions and omits the terminal boundary n
that the naive matcher includes. The fast construction counts whole-suffix
comparisons; one such comparison may inspect linearly many characters.
Query bounds exclude construction, list-index lookup and range materialization.
The baseline construction sorts n positions by insertion sort (O(n³)
worst-case work) and the scan search costs O(n · |p|). This section also
adds the textbook-complexity layers:
-
suffixArrayFast (merge sort under a comparison model) with an explicit
O(n log n) work theorem (suffixArrayFast_work_isBigO_nlogn), proved
valid by suffixArrayFast_valid against the same SuffixArrayValid
specification.
-
suffixArrayRange, the binary-search range query: two binary searches
over the sorted suffix array find the lower/upper bounds of the pattern's
interval. suffixArrayRange_mem_iff proves the returned range is sound
and complete, and suffixArrayQueryWork_le bounds the query work by
2 · (|p| + 1) · (⌊log₂ n⌋ + 2) character comparisons under the stated
string-comparison model (jointly O(|p| log n), via
suffixArrayQueryWork_isBigO_logn).
Notation conventions used in this section:
-
t : the text (a Text α, i.e. List α)
-
p : a pattern (also a List α)
-
n : t.length
-
i, j : positions (natural numbers, 0-indexed)
namespace CLRSnamespace Chapter32open Chapter03variable {α : Type} [LinearOrder α]
The suffix of t starting at position i (the substring t[i:]).
def suffixAt (t : Text α) (i : ℕ) : Text α := t.drop i
Lexicographic order on suffixes, with ties broken by the starting index:
suffix t i < suffix t j, or equal suffixes with i ≤ j.
suffixLe is total: any two indices are comparable by suffix order.
instance suffixLe_total (t : Text α) : Std.Total (suffixLe t) :=
⟨fun i j => by
rcases trichotomous_of (· < ·) (suffixAt t i) (suffixAt t j) with h | h | h
· exact Or.inl (Or.inl h)
· rcases le_total i j with hij | hji
· exact Or.inl (Or.inr ⟨h, hij⟩)
· exact Or.inr (Or.inr ⟨h.symm, hji⟩)
· exact Or.inr (Or.inl h)⟩
instance suffixLe_trans (t : Text α) : IsTrans ℕ (suffixLe t) :=
⟨fun i j k hij hjk => by
rcases hij with h1 | h1
· rcases hjk with h2 | h2
· exact Or.inl (List.lt_trans h1 h2)
· rcases h2 with ⟨hjk_eq, _⟩
exact Or.inl (by simpa [hjk_eq] using h1)
· rcases h1 with ⟨hij_eq, hij_le⟩
rcases hjk with h2 | h2
· exact Or.inl (by simpa [hij_eq] using h2)
· rcases h2 with ⟨hjk_eq, hjk_le⟩
exact Or.inr ⟨hij_eq.trans hjk_eq, le_trans hij_le hjk_le⟩⟩
The suffix array of t: the indices 0..t.length-1 sorted by their
suffix's lexicographic order.
def suffixArray (t : Text α) : List ℕ :=
List.insertionSort (suffixLe t) (List.range t.length)
A list is a valid suffix array for t when it is a permutation of the
indices and is sorted by the suffix order.
def SuffixArrayValid (t : Text α) (sa : List ℕ) : Prop :=
sa.Perm (List.range t.length) ∧ List.Pairwise (suffixLe t) sa
The suffix-array construction is valid: it is a sorted permutation of the
indices.
A pattern is a prefix of a text iff the text's prefix of the pattern's
length equals the pattern.
omit [LinearOrder α] in
theorem isPrefix_iff_take_eq (p s : Text α) : isPrefix p s ↔ s.take p.length = p := by
constructor
· rintro ⟨t, ht⟩
rw [← ht]
simp
· intro h
refine ⟨s.drop p.length, ?_⟩
exact (congrArg (fun x => x ++ s.drop p.length) h.symm).trans (List.take_append_drop p.length s)
Suffix-array pattern search: all indices whose suffix begins with p,
in suffix-array order.
def suffixArraySearch (t : Text α) (p : Text α) : List ℕ :=
(suffixArray t).filter (fun i => decide ((suffixAt t i).take p.length = p))
Soundness and completeness of suffix-array search. An index i is
returned iff i is a valid position and p is a prefix of suffixAt t i
(equivalently, p occurs at position i).
Textbook-complexity construction
The baseline above proves correctness but uses insertion sort. This section
adds a comparison-model construction: the suffix array is produced by merge
sort, and a unit of work is charged for each lexicographic suffix comparison.
The construction cost is proved to be O(n log n) comparisons, and the result
is proved to satisfy the same SuffixArrayValid specification.
One lexicographic suffix comparison, charged as a single unit of work in the
comparison model.
def suffixCompare (t : Text α) (i j : ℕ) : Bool := decide (suffixLe t i j)
suffixCompare is equivalent to suffixLe.
suffixCompare is transitive (so merge sort returns a sorted list).
suffixCompare is total (so merge sort compares any two suffixes).
Costed merge: merges two sorted lists and charges one comparison per step.
def mergeWithCost (t : Text α) : List ℕ → List ℕ → List ℕ × Nat
| [], ys => (ys, 0)
| xs, [] => (xs, 0)
| x :: xs, y :: ys =>
if suffixCompare t x y then
let r := mergeWithCost t xs (y :: ys)
(x :: r.1, r.2 + 1)
else
let r := mergeWithCost t (x :: xs) ys
(y :: r.1, r.2 + 1)
Costed merge sort, splitting at (n+1)/2 exactly like List.mergeSort.
def mergeSortWithCost (t : Text α) : List ℕ → List ℕ × Nat
| [] => ([], 0)
| [x] => ([x], 0)
| a :: b :: xs =>
let lr := (a :: b :: xs).splitAt (((a :: b :: xs).length + 1) / 2)
let sl := mergeSortWithCost t lr.1
let sr := mergeSortWithCost t lr.2
let sm := mergeWithCost t sl.1 sr.1
(sm.1, sl.2 + sr.2 + sm.2)
termination_by xs => xs.length
Erasing the merge cost recovers List.merge.
theorem mergeWithCost_result (t : Text α) (xs ys : List ℕ) :
(mergeWithCost t xs ys).1 = List.merge xs ys (suffixCompare t) := by
induction h : xs.length + ys.length using Nat.strong_induction_on generalizing xs ys with
| h n ih =>
cases xs with
| nil => simp [mergeWithCost]
| cons x xs =>
cases ys with
| nil => simp [mergeWithCost]
| cons y ys =>
by_cases hc : suffixCompare t x y
· simp [mergeWithCost, hc]
apply ih (xs.length + (y :: ys).length) ?_ xs (y :: ys) rfl
simp [List.length_cons] at *
omega
· simp [mergeWithCost, hc]
apply ih ((x :: xs).length + ys.length) ?_ (x :: xs) ys rfl
simp [List.length_cons] at *
omega
A merge preserves the multiset of the two input lists.
A merge of two sorted lists is sorted.
(n + 1) / 2 < n for 2 ≤ n.
theorem half_succ_lt_self (n : ℕ) (hn : 2 ≤ n) : (n + 1) / 2 < n := by omega
theorem sub_half_succ_eq_half (n : ℕ) : n - (n + 1) / 2 = n / 2 := by omega
theorem div_two_lt_self (n : ℕ) (hn : 1 ≤ n) : n / 2 < n := by omega
Merge sort is a permutation.
theorem mergeSortWithCost_perm (t : Text α) (xs : List ℕ) :
(mergeSortWithCost t xs).1.Perm xs := by
induction h : xs.length using Nat.strong_induction_on generalizing xs with
| h n ih =>
cases xs with
| nil => simp [mergeSortWithCost]
| cons a rest =>
cases rest with
| nil => simp [mergeSortWithCost]
| cons b rest =>
simp only [mergeSortWithCost]
rw [List.splitAt_eq]
let l1 := (a :: b :: rest).take (((a :: b :: rest).length + 1) / 2)
let l2 := (a :: b :: rest).drop (((a :: b :: rest).length + 1) / 2)
change (mergeWithCost t (mergeSortWithCost t l1).1
(mergeSortWithCost t l2).1).1.Perm (a :: b :: rest)
have hlt1 : l1.length < n := by
have hL : 2 ≤ (a :: b :: rest).length := by simp [List.length_cons]
calc
l1.length ≤ ((a :: b :: rest).length + 1) / 2 := by simp [l1, List.length_take]
_ < (a :: b :: rest).length := half_succ_lt_self _ hL
_ = n := h
have hlt2 : l2.length < n := by
have hL : 1 ≤ (a :: b :: rest).length := by simp [List.length_cons]
calc
l2.length = (a :: b :: rest).length - ((a :: b :: rest).length + 1) / 2 := by
simp [l2, List.length_drop]
_ = (a :: b :: rest).length / 2 := sub_half_succ_eq_half _
_ < (a :: b :: rest).length := div_two_lt_self _ hL
_ = n := h
have h1 : (mergeSortWithCost t l1).1.Perm l1 := ih l1.length hlt1 l1 rfl
have h2 : (mergeSortWithCost t l2).1.Perm l2 := ih l2.length hlt2 l2 rfl
have hmerge := mergeWithCost_perm t (mergeSortWithCost t l1).1
(mergeSortWithCost t l2).1
exact hmerge.trans ((h1.append h2).trans (by
rw [List.take_append_drop]))
Merge sort returns a sorted list.
theorem mergeSortWithCost_sorted (t : Text α) (xs : List ℕ) :
List.Pairwise (suffixLe t) (mergeSortWithCost t xs).1 := by
induction h : xs.length using Nat.strong_induction_on generalizing xs with
| h n ih =>
cases xs with
| nil => simp [mergeSortWithCost]
| cons a rest =>
cases rest with
| nil => simp [mergeSortWithCost]
| cons b rest =>
simp only [mergeSortWithCost]
rw [List.splitAt_eq]
let l1 := (a :: b :: rest).take (((a :: b :: rest).length + 1) / 2)
let l2 := (a :: b :: rest).drop (((a :: b :: rest).length + 1) / 2)
change List.Pairwise (suffixLe t)
(mergeWithCost t (mergeSortWithCost t l1).1 (mergeSortWithCost t l2).1).1
have hlt1 : l1.length < n := by
have hL : 2 ≤ (a :: b :: rest).length := by simp [List.length_cons]
calc
l1.length ≤ ((a :: b :: rest).length + 1) / 2 := by simp [l1, List.length_take]
_ < (a :: b :: rest).length := half_succ_lt_self _ hL
_ = n := h
have hlt2 : l2.length < n := by
have hL : 1 ≤ (a :: b :: rest).length := by simp [List.length_cons]
calc
l2.length = (a :: b :: rest).length - ((a :: b :: rest).length + 1) / 2 := by
simp [l2, List.length_drop]
_ = (a :: b :: rest).length / 2 := sub_half_succ_eq_half _
_ < (a :: b :: rest).length := div_two_lt_self _ hL
_ = n := h
have h1 : List.Pairwise (suffixLe t) (mergeSortWithCost t l1).1 :=
ih l1.length hlt1 l1 rfl
have h2 : List.Pairwise (suffixLe t) (mergeSortWithCost t l2).1 :=
ih l2.length hlt2 l2 rfl
exact mergeWithCost_sorted t h1 h2
A merge charges at most one comparison per merged element.
theorem mergeWithCost_cost_le (t : Text α) (xs ys : List ℕ) :
(mergeWithCost t xs ys).2 ≤ xs.length + ys.length := by
induction h : xs.length + ys.length using Nat.strong_induction_on generalizing xs ys with
| h n ih =>
cases xs with
| nil => simp [mergeWithCost]
| cons x xs =>
cases ys with
| nil => simp [mergeWithCost]
| cons y ys =>
by_cases hc : suffixCompare t x y
· simp [mergeWithCost, hc]
have hrec := ih (xs.length + (y :: ys).length) (by
simp [List.length_cons] at *; omega) xs (y :: ys) rfl
simp [List.length_cons] at *
omega
· simp [mergeWithCost, hc]
have hrec := ih ((x :: xs).length + ys.length) (by
simp [List.length_cons] at *; omega) (x :: xs) ys rfl
simp [List.length_cons] at *
omega
Nat.clog 2 n ≤ Nat.log 2 n + 1.
theorem clog_two_le_log_two_add_one (n : ℕ) :
Nat.clog 2 n ≤ Nat.log 2 n + 1 := by
rw [Nat.clog_le_iff_le_pow (by norm_num : 1 < 2)]
exact Nat.le_of_lt (Nat.lt_pow_succ_log_self (by norm_num : 1 < 2) n)
Halving drops the ceiling-log by one (for n ≥ 2).
theorem clog_two_ceil_half_le_pred (n : ℕ) (hn : 2 ≤ n) :
Nat.clog 2 ((n + 1) / 2) ≤ Nat.clog 2 n - 1 := by
have h := Nat.clog_of_two_le (by norm_num : 1 < 2) hn
have h' : n + 2 - 1 = n + 1 := by omega
rw [h'] at h
rw [h]
omega
The floor half also drops the ceiling-log by one (for n ≥ 2).
theorem clog_two_floor_half_le_pred (n : ℕ) (hn : 2 ≤ n) :
Nat.clog 2 (n / 2) ≤ Nat.clog 2 n - 1 := by
have hdiv : n / 2 ≤ (n + 1) / 2 := Nat.div_le_div_right (by omega : n ≤ n + 1)
exact (Nat.clog_mono_right 2 hdiv).trans (clog_two_ceil_half_le_pred n hn)
Merge sort performs at most length · ⌈log₂ length⌉ comparisons.
theorem mergeSortWithCost_cost_le_clog (t : Text α) (xs : List ℕ) :
(mergeSortWithCost t xs).2 ≤ xs.length * Nat.clog 2 xs.length := by
induction h : xs.length using Nat.strong_induction_on generalizing xs with
| h n ih =>
cases xs with
| nil => simp [mergeSortWithCost]
| cons a rest =>
cases rest with
| nil => simp [mergeSortWithCost]
| cons b rest =>
simp only [mergeSortWithCost]
rw [List.splitAt_eq]
let l1 := List.take (((a :: b :: rest).length + 1) / 2) (a :: b :: rest)
let l2 := List.drop (((a :: b :: rest).length + 1) / 2) (a :: b :: rest)
change (mergeSortWithCost t l1).2 + (mergeSortWithCost t l2).2 +
(mergeWithCost t (mergeSortWithCost t l1).1 (mergeSortWithCost t l2).1).2 ≤
n * Nat.clog 2 n
have hlen1 : l1.length = ((a :: b :: rest).length + 1) / 2 := by
simp [l1, List.length_take]; omega
have hlen2 : l2.length = (a :: b :: rest).length / 2 := by
simp [l2, List.length_drop]; omega
have hlt1 : l1.length < n := by
have hL : 2 ≤ (a :: b :: rest).length := by simp [List.length_cons]
calc
l1.length ≤ ((a :: b :: rest).length + 1) / 2 := by simp [l1, List.length_take]
_ < (a :: b :: rest).length := half_succ_lt_self _ hL
_ = n := h
have hlt2 : l2.length < n := by
have hL : 1 ≤ (a :: b :: rest).length := by simp [List.length_cons]
calc
l2.length = (a :: b :: rest).length - ((a :: b :: rest).length + 1) / 2 := by
simp [l2, List.length_drop]
_ = (a :: b :: rest).length / 2 := sub_half_succ_eq_half _
_ < (a :: b :: rest).length := div_two_lt_self _ hL
_ = n := h
have h1 := ih l1.length hlt1 l1 rfl
have h2 := ih l2.length hlt2 l2 rfl
have hmerge := mergeWithCost_cost_le t (mergeSortWithCost t l1).1
(mergeSortWithCost t l2).1
have hlen1' : (mergeSortWithCost t l1).1.length = l1.length :=
(mergeSortWithCost_perm t l1).length_eq
have hlen2' : (mergeSortWithCost t l2).1.length = l2.length :=
(mergeSortWithCost_perm t l2).length_eq
have hclog1 : Nat.clog 2 l1.length + 1 ≤ Nat.clog 2 (a :: b :: rest).length := by
have hpos : 1 ≤ Nat.clog 2 (a :: b :: rest).length :=
Nat.clog_pos (by norm_num) (by simp [List.length_cons])
have hc := clog_two_ceil_half_le_pred (a :: b :: rest).length (by simp)
rw [hlen1]
omega
have hclog2 : Nat.clog 2 l2.length + 1 ≤ Nat.clog 2 (a :: b :: rest).length := by
have hpos : 1 ≤ Nat.clog 2 (a :: b :: rest).length :=
Nat.clog_pos (by norm_num) (by simp [List.length_cons])
have hc := clog_two_floor_half_le_pred (a :: b :: rest).length (by simp)
rw [hlen2]
omega
have hlen_sum : l1.length + l2.length = (a :: b :: rest).length := by
rw [hlen1, hlen2]; simp; omega
have h1c : (mergeSortWithCost t l1).2 + l1.length ≤
l1.length * Nat.clog 2 (a :: b :: rest).length := by
have hdist : l1.length * Nat.clog 2 l1.length + l1.length =
l1.length * (Nat.clog 2 l1.length + 1) := by ring
nlinarith [h1, hclog1]
have h2c : (mergeSortWithCost t l2).2 + l2.length ≤
l2.length * Nat.clog 2 (a :: b :: rest).length := by
nlinarith [h2, hclog2]
have hmerge' : (mergeWithCost t (mergeSortWithCost t l1).1
(mergeSortWithCost t l2).1).2 ≤ l1.length + l2.length := by
simpa [hlen1', hlen2'] using hmerge
calc
(mergeSortWithCost t l1).2 + (mergeSortWithCost t l2).2 +
(mergeWithCost t (mergeSortWithCost t l1).1
(mergeSortWithCost t l2).1).2 ≤
(mergeSortWithCost t l1).2 + (mergeSortWithCost t l2).2 +
(l1.length + l2.length) := Nat.add_le_add_left hmerge' _
_ ≤ l1.length * Nat.clog 2 (a :: b :: rest).length +
l2.length * Nat.clog 2 (a :: b :: rest).length := by
nlinarith [h1c, h2c]
_ = n * Nat.clog 2 n := by
rw [← Nat.add_mul, hlen_sum, h]
Merge sort performs at most length · (⌊log₂ length⌋ + 1) comparisons.
The fast suffix-array construction (comparison model, merge sort).
The comparison work of the fast suffix-array construction.
The fast construction is a valid suffix array.
The fast construction performs at most n · (⌊log₂ n⌋ + 1) comparisons.
The fast construction is O(n log n) under the comparison model.
theorem suffixArrayFast_work_isBigO_nlogn :
isBigO (fun n : ℕ => (n * Nat.log 2 n + n : ℝ))
(fun n : ℕ => (n : ℝ) * (Nat.log 2 n : ℝ)) := by
rw [isBigO_iff]
refine ⟨2, by norm_num, 2, fun n hn => ?_⟩
have hlog : (1 : ℝ) ≤ (Nat.log 2 n : ℝ) := by
exact_mod_cast (Nat.log_pos (by norm_num : 1 < 2) hn)
rw [abs_of_nonneg (by positivity), abs_of_nonneg (by positivity)]
have hn' : (0 : ℝ) ≤ n := by positivity
have hmul : (n : ℝ) ≤ (n : ℝ) * (Nat.log 2 n : ℝ) := by
calc
(n : ℝ) = 1 * (n : ℝ) := by ring
_ ≤ (Nat.log 2 n : ℝ) * (n : ℝ) := mul_le_mul_of_nonneg_right hlog hn'
_ = (n : ℝ) * (Nat.log 2 n : ℝ) := by ring
calc
(n : ℝ) * (Nat.log 2 n : ℝ) + (n : ℝ) ≤
(n : ℝ) * (Nat.log 2 n : ℝ) + (n : ℝ) * (Nat.log 2 n : ℝ) :=
add_le_add_right hmul ((n : ℝ) * (Nat.log 2 n : ℝ))
_ = 2 * ((n : ℝ) * (Nat.log 2 n : ℝ)) := by ring
Textbook-complexity range query
The O(n log n) construction above gives a sorted suffix array. This section
adds the other half of CLRS §32.5: a pattern search that finds every occurrence
of p by two binary searches over that array. Each probe compares p
against one suffix; in the stated string-comparison model a probe costs at most
|p| + 1 character comparisons, so the whole query runs in O(|p| log n).
A suffix begins with p exactly when it lies between the two bounds
-
patternLE p s: p ≤ s lexicographically (the lower-bound predicate),
and
-
patternGT p s: p < s and p is not a prefix of s (the
upper-bound predicate).
Because the suffix array is sorted by suffixLe, both predicates are
monotone along it, so each bound is found by binary search.
p is at-or-before suffix s in lexicographic order: the lower-bound
predicate of the range query.
def patternLE (p s : Text α) : Prop := p ≤ s
s is strictly after every suffix that begins with p: the upper-bound
predicate of the range query.
def patternGT (p s : Text α) : Prop := p < s ∧ s.take p.length ≠ p
instance patternLE_decidable (p s : Text α) : Decidable (patternLE p s) := by
unfold patternLE; infer_instance
instance patternGT_decidable (p s : Text α) : Decidable (patternGT p s) := by
unfold patternGT; infer_instance
The empty list is at-or-before every list in lexicographic order.
theorem nil_le (l : Text α) : [] ≤ l := by
rcases l with _ | ⟨b, l⟩
· exact le_rfl
· exact le_of_lt ((List.lt_iff_lex_lt [] (b :: l)).mp List.Lex.nil)
Taking a prefix is monotone with respect to lexicographic order.
theorem take_lex_le {s₁ s₂ : Text α} (hlex : List.Lex (· < ·) s₁ s₂) :
∀ k, s₁.take k ≤ s₂.take k := by
induction hlex with
| nil =>
rename_i b l
intro k
simpa using (nil_le ((b :: l).take k))
| rel hlt => intro k; cases k with
| zero => simp
| succ k => exact le_of_lt ((List.lt_iff_lex_lt _ _).mp (List.Lex.rel hlt))
| cons h ih => intro k; cases k with
| zero => simp
| succ k => exact List.cons_le_cons _ (ih k)
Taking a prefix is monotone with respect to lexicographic order.
theorem take_le_take {s₁ s₂ : Text α} (h : s₁ ≤ s₂) : ∀ k, s₁.take k ≤ s₂.take k := by
rcases lt_or_eq_of_le h with hlt | rfl
· exact take_lex_le ((List.lt_iff_lex_lt s₁ s₂).mp hlt)
· intro k; rfl
A prefix is at-or-before its extension in lexicographic order.
theorem le_of_isPrefix {p s : Text α} (h : isPrefix p s) : p ≤ s := by
rcases h with ⟨r, rfl⟩
exact le_iff_lt_or_eq.mpr <| match r with
| [] => Or.inr (by simp)
| b :: r' =>
Or.inl ((List.lt_iff_lex_lt p (p ++ b :: r')).mp
(by simpa using (List.Lex.append_left (· < ·)
(List.Lex.nil : List.Lex (· < ·) [] (b :: r')) p)))
If p ≤ s₁ ≤ s₂ and p is a prefix of s₂, then p is a prefix of s₁.
theorem isPrefix_of_le_of_isPrefix {p s₁ s₂ : Text α}
(hps : p ≤ s₁) (hss : s₁ ≤ s₂) (hp₂ : isPrefix p s₂) : isPrefix p s₁ := by
have ht : s₂.take p.length = p := (isPrefix_iff_take_eq p s₂).mp hp₂
have h₁ : s₁.take p.length ≤ s₂.take p.length := take_le_take hss p.length
have h₂ : p ≤ s₁.take p.length := by simpa using (take_le_take hps p.length)
have : s₁.take p.length = p := le_antisymm (by simpa [ht] using h₁) h₂
exact (isPrefix_iff_take_eq p s₁).mpr this
patternLE is monotone in the suffix argument.
theorem patternLE_mono {p s₁ s₂ : Text α} (h₁ : patternLE p s₁) (hss : s₁ ≤ s₂) :
patternLE p s₂ := le_trans h₁ hss
patternGT is monotone in the suffix argument.
A pattern is a prefix of s exactly when it lies between the lower and
upper bounds.
theorem isPrefix_iff_patternLE_and_not_patternGT (p s : Text α) :
isPrefix p s ↔ patternLE p s ∧ ¬ patternGT p s := by
constructor
· intro hpfx
constructor
· exact le_of_isPrefix hpfx
· intro hgt
exact hgt.2 ((isPrefix_iff_take_eq p s).mp hpfx)
· intro h
rcases h with ⟨hle, hngt⟩
rcases lt_or_eq_of_le hle with hlt | heq
· by_cases hpfx : s.take p.length = p
· exact (isPrefix_iff_take_eq p s).mpr hpfx
· exact False.elim (hngt ⟨hlt, hpfx⟩)
· subst s; exact ⟨[], by simp⟩
suffixLe orders suffixes by their lexicographic order.
theorem suffixAt_le_of_suffixLe {t : Text α} {i j : ℕ} (h : suffixLe t i j) :
suffixAt t i ≤ suffixAt t j := by
rcases h with hlt | ⟨heq, _⟩
· exact le_of_lt hlt
· exact le_of_eq heq
In a suffix-array-sorted list, suffixes at smaller positions are at-or-before
suffixes at larger positions.
theorem sorted_suffixAt_le {t : Text α} {sa : List ℕ}
(hsorted : List.Pairwise (suffixLe t) sa) {i j : ℕ}
(hi : i < sa.length) (hj : j < sa.length) (hij : i < j) :
suffixAt t sa[i] ≤ suffixAt t sa[j] := by
exact suffixAt_le_of_suffixLe
(List.Pairwise.rel_get_of_lt hsorted (a := ⟨i, hi⟩) (b := ⟨j, hj⟩) hij)
Binary search
A single reusable costed binary search finds the first index in a list where a
monotone boolean predicate turns true.
Costed binary search for the first index k in [lo, hi) with
P (sa.getD k 0) true, charging one probe per comparison.
def binarySearchFirstCostAux (P : ℕ → Bool) (sa : List ℕ) (lo hi : ℕ) : ℕ × Nat :=
if lo < hi then
let mid := (lo + hi) / 2
if P (sa.getD mid 0) then
let r := binarySearchFirstCostAux P sa lo mid
(r.1, r.2 + 1)
else
let r := binarySearchFirstCostAux P sa (mid + 1) hi
(r.1, r.2 + 1)
else
(lo, 0)
termination_by hi - lo
The pure binary search, erasing the probe count.
def binarySearchFirstAux (P : ℕ → Bool) (sa : List ℕ) (lo hi : ℕ) : ℕ :=
if lo < hi then
let mid := (lo + hi) / 2
if P (sa.getD mid 0) then
binarySearchFirstAux P sa lo mid
else
binarySearchFirstAux P sa (mid + 1) hi
else
lo
termination_by hi - lo
Erasing the cost recovers the pure binary search.
theorem binarySearchFirstCostAux_fst (P : ℕ → Bool) (sa : List ℕ) (lo hi : ℕ) :
(binarySearchFirstCostAux P sa lo hi).1 = binarySearchFirstAux P sa lo hi := by
induction h : hi - lo using Nat.strong_induction_on generalizing lo hi with
| h d ih =>
unfold binarySearchFirstCostAux binarySearchFirstAux
by_cases hlt : lo < hi
· simp only [hlt, ↓reduceIte]
by_cases hP : P (sa.getD ((lo + hi) / 2) 0)
· simp only [hP, ↓reduceIte]
exact ih (((lo + hi) / 2) - lo) (by omega) lo ((lo + hi) / 2) rfl
· simp only [hP, This simp argument is unused:
↓reduceIte
Hint: Omit it from the simp argument list.
simp only [hP,̵ ̵↓̵r̵e̵d̵u̵c̵e̵I̵t̵e̵]
Note: This linter can be disabled with `set_option linter.unusedSimpArgs false`↓reduceIte]
exact ih (hi - ((lo + hi) / 2 + 1)) (by omega) ((lo + hi) / 2 + 1) hi rfl
· simp only [hlt, ↓reduceIte]
r is the first index in [lo, hi] where P holds along sa.
def BinarySearchSpec (P : ℕ → Bool) (sa : List ℕ) (lo hi r : ℕ) : Prop :=
lo ≤ r ∧ r ≤ hi ∧
(∀ k, lo ≤ k → k < r → P (sa.getD k 0) = false) ∧
(r < hi → P (sa.getD r 0) = true)
The binary search returns the first index with P true (or hi if none).
theorem binarySearchFirstAux_spec (P : ℕ → Bool) (sa : List ℕ)
(hmono : ∀ ⦃i j⦄, i < j → j < sa.length →
P (sa.getD i 0) = true → P (sa.getD j 0) = true) :
∀ lo hi, lo ≤ hi → hi ≤ sa.length →
(∀ k, k < lo → P (sa.getD k 0) = false) →
(∀ k, hi ≤ k → k < sa.length → P (sa.getD k 0) = true) →
BinarySearchSpec P sa lo hi (binarySearchFirstAux P sa lo hi) := by
intro lo hi
induction h : hi - lo using Nat.strong_induction_on generalizing lo hi with
| h d ih =>
intro hle hhi hL hR
unfold binarySearchFirstAux
by_cases hlt : lo < hi
· have hmid_lo : lo ≤ (lo + hi) / 2 := by
exact (Nat.le_div_iff_mul_le (by decide : 0 < 2)).mpr (by omega)
have hmid_hi : (lo + hi) / 2 < hi := by
exact (Nat.div_lt_iff_lt_mul (by decide : 0 < 2)).mpr (by omega)
have hmid_len : (lo + hi) / 2 < sa.length := lt_of_lt_of_le hmid_hi hhi
simp only [hlt, ↓reduceIte]
by_cases hP : P (sa.getD ((lo + hi) / 2) 0) = true
· rw [if_pos hP]
have hR' : ∀ k, (lo + hi) / 2 ≤ k → k < sa.length → P (sa.getD k 0) = true := by
intro k hkmid hkl
by_cases hk : k = (lo + hi) / 2
· subst k; exact hP
· have hmid_lt_k : (lo + hi) / 2 < k := lt_of_le_of_ne hkmid (Ne.symm hk)
exact hmono hmid_lt_k hkl hP
have hspec := ih ((lo + hi) / 2 - lo) (by omega) lo ((lo + hi) / 2) rfl
hmid_lo (le_of_lt hmid_len) hL hR'
rcases hspec with ⟨hrlo, hrhi, hfalse, htrue⟩
constructor
· exact hrlo
constructor
· exact le_trans hrhi (le_of_lt hmid_hi)
constructor
· exact hfalse
· intro hrhi'
by_cases hrm : binarySearchFirstAux P sa lo ((lo + hi) / 2) < (lo + hi) / 2
· exact htrue hrm
· have hreq : binarySearchFirstAux P sa lo ((lo + hi) / 2) = (lo + hi) / 2 :=
le_antisymm hrhi (le_of_not_gt hrm)
simpa [hreq] using hP
· rw [if_neg hP]
have hPfalse : P (sa.getD ((lo + hi) / 2) 0) = false := by
simpa [Bool.not_eq_true] using hP
have hmid1_hi : (lo + hi) / 2 + 1 ≤ hi := by omega
have hL' : ∀ k, k < (lo + hi) / 2 + 1 → P (sa.getD k 0) = false := by
intro k hklt
by_cases hklo : k < lo
· exact hL k hklo
· have hk_le_mid : k ≤ (lo + hi) / 2 := by omega
by_cases hkm : k = (lo + hi) / 2
· subst k; exact hPfalse
· have hk_lt_mid : k < (lo + hi) / 2 := lt_of_le_of_ne hk_le_mid hkm
have hkmid_true : P (sa.getD k 0) = true → False := by
intro hkP
exact hP (hmono hk_lt_mid hmid_len hkP)
by_cases hc : P (sa.getD k 0) = true
· exact (hkmid_true hc).elim
· exact (Bool.not_eq_true _).mp hc
have hspec := ih (hi - ((lo + hi) / 2 + 1)) (by omega) ((lo + hi) / 2 + 1) hi rfl
hmid1_hi hhi hL' hR
rcases hspec with ⟨hrlo, hrhi, hfalse, htrue⟩
constructor
· exact le_trans hmid_lo (le_trans (by omega) hrlo)
constructor
· exact hrhi
constructor
· intro k hklo hkr
by_cases hk_mid : k ≤ (lo + hi) / 2
· exact hL' k (by omega)
· have hmid1_k : (lo + hi) / 2 + 1 ≤ k := by omega
exact hfalse k hmid1_k hkr
· exact htrue
· simp only [hlt, ↓reduceIte]
constructor
· omega
constructor
· omega
constructor
· intro k hklo hkr; omega
· intro hrhi; omega
Halving a ceiling-log: clog 2 (n/2 + 1) ≤ clog 2 (n+1) - 1 for n ≥ 1.
theorem clog_two_half_add_one_le_pred (n : ℕ) (hn : 1 ≤ n) :
Nat.clog 2 (n / 2 + 1) ≤ Nat.clog 2 (n + 1) - 1 := by
have hh := clog_two_ceil_half_le_pred (n + 1) (by omega : 2 ≤ n + 1)
have hhalf : (n + 1 + 1) / 2 = n / 2 + 1 := by omega
simpa [hhalf] using hh
The costed binary search performs at most ⌈log₂ (hi - lo + 1)⌉ probes.
theorem binarySearchFirstCostAux_cost_le (P : ℕ → Bool) (sa : List ℕ) (lo hi : ℕ) :
(binarySearchFirstCostAux P sa lo hi).2 ≤ Nat.clog 2 (hi - lo + 1) := by
induction h : hi - lo using Nat.strong_induction_on generalizing lo hi with
| h d ih =>
unfold binarySearchFirstCostAux
by_cases hlt : lo < hi
· have hmid_lo : lo ≤ (lo + hi) / 2 := by
exact (Nat.le_div_iff_mul_le (by decide : 0 < 2)).mpr (by omega)
have hmid_hi : (lo + hi) / 2 < hi := by
exact (Nat.div_lt_iff_lt_mul (by decide : 0 < 2)).mpr (by omega)
simp only [hlt, ↓reduceIte]
by_cases hP : P (sa.getD ((lo + hi) / 2) 0) = true
· rw [if_pos hP, ← h]
have hrec := ih (((lo + hi) / 2) - lo) (by omega) lo ((lo + hi) / 2) rfl
have hmid_eq : (lo + hi) / 2 - lo = (hi - lo) / 2 := by omega
rw [hmid_eq] at hrec
have hclogpos : 1 ≤ Nat.clog 2 (hi - lo + 1) := by
exact Nat.succ_le_of_lt (Nat.clog_pos (by decide : 1 < 2) (by omega : 2 ≤ hi - lo + 1))
have hclog : Nat.clog 2 ((hi - lo) / 2 + 1) ≤ Nat.clog 2 (hi - lo + 1) - 1 := by
exact clog_two_half_add_one_le_pred (hi - lo) (by omega)
have hstep : Nat.clog 2 ((hi - lo) / 2 + 1) + 1 ≤ Nat.clog 2 (hi - lo + 1) :=
Nat.add_le_of_le_sub hclogpos hclog
calc
(binarySearchFirstCostAux P sa lo ((lo + hi) / 2)).2 + 1
≤ Nat.clog 2 ((hi - lo) / 2 + 1) + 1 := Nat.add_le_add_right hrec 1
_ ≤ Nat.clog 2 (hi - lo + 1) := hstep
· rw [if_neg hP, ← h]
have hrec := ih (hi - ((lo + hi) / 2 + 1)) (by omega) ((lo + hi) / 2 + 1) hi rfl
have hsub_le : hi - ((lo + hi) / 2 + 1) ≤ (hi - lo) / 2 := by omega
have hclogpos : 1 ≤ Nat.clog 2 (hi - lo + 1) := by
exact Nat.succ_le_of_lt (Nat.clog_pos (by decide : 1 < 2) (by omega : 2 ≤ hi - lo + 1))
have hclog' : Nat.clog 2 (hi - ((lo + hi) / 2 + 1) + 1) ≤ Nat.clog 2 ((hi - lo) / 2 + 1) := by
exact Nat.clog_mono_right 2 (by omega)
have hclog : Nat.clog 2 ((hi - lo) / 2 + 1) ≤ Nat.clog 2 (hi - lo + 1) - 1 := by
exact clog_two_half_add_one_le_pred (hi - lo) (by omega)
have hstep : Nat.clog 2 ((hi - lo) / 2 + 1) + 1 ≤ Nat.clog 2 (hi - lo + 1) :=
Nat.add_le_of_le_sub hclogpos hclog
calc
(binarySearchFirstCostAux P sa ((lo + hi) / 2 + 1) hi).2 + 1
≤ Nat.clog 2 (hi - ((lo + hi) / 2 + 1) + 1) + 1 := Nat.add_le_add_right hrec 1
_ ≤ Nat.clog 2 ((hi - lo) / 2 + 1) + 1 := Nat.add_le_add_right hclog' 1
_ ≤ Nat.clog 2 (hi - lo + 1) := hstep
· simp only [hlt, ↓reduceIte]
exact Nat.zero_le _
Binary search for the first index in a whole list with P true.
The costed binary search over a whole list.
The whole-list binary search returns the first index with P true.
theorem binarySearchFirst_spec (P : ℕ → Bool) (sa : List ℕ)
(hmono : ∀ ⦃i j⦄, i < j → j < sa.length →
P (sa.getD i 0) = true → P (sa.getD j 0) = true) :
(binarySearchFirst P sa) ≤ sa.length ∧
(∀ k, k < binarySearchFirst P sa → P (sa.getD k 0) = false) ∧
(binarySearchFirst P sa < sa.length → P (sa.getD (binarySearchFirst P sa) 0) = true) := by
have hspec := binarySearchFirstAux_spec P sa hmono 0 sa.length
(Nat.zero_le _) le_rfl (by intro k hk; omega) (by intro k hk hkl; omega)
rcases hspec with ⟨hrlo, hrhi, hfalse, htrue⟩
constructor
· exact hrhi
constructor
· intro k hkr
exact hfalse k (Nat.zero_le _) hkr
· exact htrue
The whole-list costed binary search performs at most ⌈log₂ (n+1)⌉ probes.
The decidable lower-bound probe: does the suffix at position x reach the
pattern?
The decidable upper-bound probe: is the suffix at position x strictly past
every suffix beginning with p?
lowerDecide is monotone along a sorted suffix array.
theorem lowerDecide_mono {t : Text α} {p : Text α} {sa : List ℕ}
(hsorted : List.Pairwise (suffixLe t) sa) (i j : ℕ)
(hij : i < j) (hj : j < sa.length) :
lowerDecide t p (sa.getD i 0) = true → lowerDecide t p (sa.getD j 0) = true := by
intro hi
have hi_lt : i < sa.length := lt_trans hij hj
have hle : suffixAt t (sa.getD i 0) ≤ suffixAt t (sa.getD j 0) := by
have hg : suffixAt t sa[i] ≤ suffixAt t sa[j] :=
sorted_suffixAt_le hsorted hi_lt hj hij
have hiD : sa.getD i 0 = sa[i] := List.getD_eq_getElem sa 0 hi_lt
have hjD : sa.getD j 0 = sa[j] := List.getD_eq_getElem sa 0 hj
simpa only [hiD, hjD] using hg
have hle' : patternLE p (suffixAt t (sa.getD i 0)) := of_decide_eq_true hi
have hle'' : patternLE p (suffixAt t (sa.getD j 0)) := patternLE_mono hle' hle
exact decide_eq_true hle''
upperDecide is monotone along a sorted suffix array.
theorem upperDecide_mono {t : Text α} {p : Text α} {sa : List ℕ}
(hsorted : List.Pairwise (suffixLe t) sa) (i j : ℕ)
(hij : i < j) (hj : j < sa.length) :
upperDecide t p (sa.getD i 0) = true → upperDecide t p (sa.getD j 0) = true := by
intro hi
have hi_lt : i < sa.length := lt_trans hij hj
have hle : suffixAt t (sa.getD i 0) ≤ suffixAt t (sa.getD j 0) := by
have hg : suffixAt t sa[i] ≤ suffixAt t sa[j] :=
sorted_suffixAt_le hsorted hi_lt hj hij
have hiD : sa.getD i 0 = sa[i] := List.getD_eq_getElem sa 0 hi_lt
have hjD : sa.getD j 0 = sa[j] := List.getD_eq_getElem sa 0 hj
simpa only [hiD, hjD] using hg
have hle' : patternGT p (suffixAt t (sa.getD i 0)) := of_decide_eq_true hi
have hle'' : patternGT p (suffixAt t (sa.getD j 0)) := patternGT_mono hle' hle
exact decide_eq_true hle''
The lower bound of the pattern's interval in the fast suffix array.
The upper bound of the pattern's interval in the fast suffix array.
The lower bound is at most the upper bound.
The fast range query: the slice of the fast suffix array whose suffixes
begin with p.
The character-comparison work of the fast range query: two binary searches,
each probe charged |p| + 1 character comparisons.
The lower bound of the interval is where suffixes first reach p.
The upper bound of the interval is where suffixes first move past p.
Membership in the slice (l.drop lo).take (hi - lo).
theorem mem_drop_take_iff (l : List ℕ) (lo hi x : ℕ) (hlo : lo ≤ hi) :
x ∈ (l.drop lo).take (hi - lo) ↔ ∃ j, lo ≤ j ∧ j < hi ∧ l[j]? = some x := by
rw [List.mem_iff_getElem?]
constructor
· rintro ⟨k, hk⟩
rw [List.getElem?_take, List.getElem?_drop] at hk
have hklt : k < hi - lo := by
by_cases h : k < hi - lo
· exact h
· simp [h] at hk
have hsome : l[lo + k]? = some x := by
simpa [hklt] using hk
refine ⟨lo + k, by omega, by omega, hsome⟩
· rintro ⟨j, hjlo, hjhi, hsome⟩
refine ⟨j - lo, ?_⟩
have hjlt : j - lo < hi - lo := by omega
rw [List.getElem?_take, List.getElem?_drop]
simp [hjlt]
have : lo + (j - lo) = j := by omega
simpa [this] using hsome
Soundness and completeness of the fast range query. An index i is
returned by suffixArrayRange exactly when p is a prefix of the suffix at
i (equivalently, p occurs at position i).
theorem suffixArrayRange_mem_iff (t : Text α) (p : Text α) (i : ℕ) :
i ∈ suffixArrayRange t p ↔ i < t.length ∧ isPrefix p (suffixAt t i) := by
let sa := suffixArrayFast t
have hperm : sa.Perm (List.range t.length) := (suffixArrayFast_valid t).1
have hlo_hi : suffixArrayLower t p ≤ suffixArrayUpper t p := suffixArrayLower_le_upper t p
have hlower := suffixArrayLower_spec t p
have hupper := suffixArrayUpper_spec t p
unfold suffixArrayRange
rw [mem_drop_take_iff sa (suffixArrayLower t p) (suffixArrayUpper t p) i hlo_hi]
constructor
· rintro ⟨j, hjlo, hjhi, hsome⟩
have hj : j < sa.length := lt_of_lt_of_le hjhi hupper.1
have hsai : sa[j] = i := by
rw [List.getElem?_eq_some_iff] at hsome
exact hsome.2
have hlower_true_j : lowerDecide t p (sa.getD j 0) = true := by
by_cases hlo_eq : suffixArrayLower t p = j
· have hgoal : lowerDecide t p (sa.getD (suffixArrayLower t p) 0) = true :=
hlower.2.2 (by simpa [hlo_eq] using hj)
simpa only [hlo_eq] using hgoal
· have hlo_lt : suffixArrayLower t p < sa.length := lt_of_le_of_lt hjlo hj
have hlo_true : lowerDecide t p (sa.getD (suffixArrayLower t p) 0) = true :=
hlower.2.2 hlo_lt
have hlo_lt_j : suffixArrayLower t p < j := lt_of_le_of_ne hjlo hlo_eq
have hmono := lowerDecide_mono (t := t) (p := p) ((suffixArrayFast_valid t).2)
exact hmono (suffixArrayLower t p) j hlo_lt_j hj hlo_true
have hupper_false_j : upperDecide t p (sa.getD j 0) = false := hupper.2.1 j hjhi
have hle : patternLE p (suffixAt t (sa.getD j 0)) := of_decide_eq_true hlower_true_j
have hngt : ¬ patternGT p (suffixAt t (sa.getD j 0)) := of_decide_eq_false hupper_false_j
have hpfx : isPrefix p (suffixAt t (sa.getD j 0)) :=
(isPrefix_iff_patternLE_and_not_patternGT p (suffixAt t (sa.getD j 0))).mpr ⟨hle, hngt⟩
have hget : sa.getD j 0 = i := by
rw [List.getD_eq_getElem sa 0 hj]
exact hsai
constructor
· have hmem : i ∈ List.range t.length := by
rw [← hperm.mem_iff]
exact List.mem_iff_getElem?.mpr ⟨j, by simpa only [hget] using hsome⟩
simpa using hmem
· simpa only [hget] using hpfx
· rintro ⟨hi_len, hpfx⟩
have himem : i ∈ sa := by
rw [hperm.mem_iff]
simpa using (List.mem_range.mpr hi_len)
rcases List.mem_iff_getElem?.mp himem with ⟨j, hsome⟩
rw [List.getElem?_eq_some_iff] at hsome
have hj : j < sa.length := hsome.1
have hji : sa[j] = i := hsome.2
have hgetD : sa.getD j 0 = i := by
rw [List.getD_eq_getElem sa 0 hj]
exact hji
have hpfx_j : isPrefix p (suffixAt t (sa.getD j 0)) := by
simpa only [hgetD] using hpfx
have hboth := (isPrefix_iff_patternLE_and_not_patternGT p (suffixAt t (sa.getD j 0))).mp hpfx_j
have hlower_true : lowerDecide t p (sa.getD j 0) = true := decide_eq_true hboth.1
have hupper_false : upperDecide t p (sa.getD j 0) = false :=
decide_eq_false hboth.2
have hlo_le_j : suffixArrayLower t p ≤ j := by
by_contra hneg
have hj_lt_lo : j < suffixArrayLower t p := lt_of_not_ge hneg
have hlo_false : lowerDecide t p (sa.getD j 0) = false := hlower.2.1 j hj_lt_lo
exact Bool.noConfusion (hlo_false.symm.trans hlower_true)
have hj_lt_hi : j < suffixArrayUpper t p := by
by_contra hneg
have hhi_le_j : suffixArrayUpper t p ≤ j := le_of_not_gt hneg
have hmono := upperDecide_mono (t := t) (p := p) ((suffixArrayFast_valid t).2)
have hhi_true : upperDecide t p (sa.getD j 0) = true := by
by_cases hhj : suffixArrayUpper t p = j
· subst hhj
exact hupper.2.2 hj
· have hhi_lt_j : suffixArrayUpper t p < j := lt_of_le_of_ne hhi_le_j hhj
have hhi_len : suffixArrayUpper t p < sa.length := lt_of_lt_of_le hhi_lt_j (Nat.le_of_lt hj)
exact hmono (suffixArrayUpper t p) j hhi_lt_j hj (hupper.2.2 hhi_len)
exact Bool.noConfusion (hupper_false.symm.trans hhi_true)
refine ⟨j, hlo_le_j, hj_lt_hi, ?_⟩
rw [List.getElem?_eq_some_iff]
exact ⟨hj, hji⟩
Nat.log 2 (n+1) ≤ Nat.log 2 n + 1.
theorem log_succ_le_log_add_one (n : ℕ) : Nat.log 2 (n + 1) ≤ Nat.log 2 n + 1 := by
by_cases h : n = 0
· subst n; norm_num [Nat.log]
· have h1 : 1 ≤ n := Nat.succ_le_of_lt (Nat.pos_of_ne_zero h)
have hle : n + 1 ≤ n * 2 := by omega
have hlog : Nat.log 2 (n + 1) ≤ Nat.log 2 (n * 2) := Nat.log_monotone (b := 2) hle
have hlog2 : Nat.log 2 (n * 2) = Nat.log 2 n + 1 := Nat.log_mul_base (by norm_num : 1 < 2) h
rw [hlog2] at hlog
exact hlog
Nat.clog 2 (n+1) ≤ Nat.log 2 n + 2.
The fast range query performs at most 2 · (|p| + 1) · (⌊log₂ n⌋ + 2)
character comparisons.
For a fixed pattern length m, the query work is O(log n) in the text
length under the comparison model, with the |p| factor carried in the
constant — jointly O(|p| log n).
theorem suffixArrayQueryWork_isBigO_logn (m : ℕ) :
isBigO (fun n : ℕ => (2 * ((m : ℝ) + 1) * (((Nat.log 2 n : ℕ) : ℝ) + 2)))
(fun n : ℕ => ((m : ℝ) + 1) * ((Nat.log 2 n : ℕ) : ℝ)) := by
rw [isBigO_iff]
refine ⟨8, by norm_num, 2, fun n hn => ?_⟩
have hlog : (1 : ℝ) ≤ (Nat.log 2 n : ℝ) := by
exact_mod_cast (Nat.log_pos (by norm_num : 1 < 2) (by omega : 2 ≤ n))
rw [abs_of_nonneg (by positivity), abs_of_nonneg (by positivity)]
have hm : (0 : ℝ) ≤ (m : ℝ) + 1 := by positivity
nlinarith
end Chapter32end CLRS