Suffix tree
DefinitionTerminated string#✓fully proved
For a list \(s = (s_0, \dots, s_{n-1})\) over \(\alpha\), the terminated string of \(s\) is the list \((\mathrm{some}\,s_0, \dots, \mathrm{some}\,s_{n-1}, \mathrm{none})\) over \(\mathrm{Option}\,\alpha\): every symbol of \(s\) tagged \(\mathrm{some}\), followed by the terminator \(\mathrm{none}\).
Used by 8
TheoremSuffixes of the terminated string#✓fully proved
For a list \(s\) over \(\alpha\) and a natural number \(i \le |s|\), removing the first \(i\) entries of the terminated string of \(s\) gives the suffix of \(s\) starting at index \(i\) with every symbol tagged \(\mathrm{some}\), followed by \(\mathrm{none}\).
theorem terminated_drop_eq_suffix_map (s : List α) {i : Nat} (hi : i ≤ s.length) :
(terminated s).drop i = (SuffixArray.suffix s i).map some ++ [none]
def terminated (s : List α) : List (Option α) :=
s.map some ++ [none]
CSLibExt/Algorithms/Lean/DataStructures/SuffixTree.lean:60
def suffix (s : List α) (i : Nat) : List α :=
s.drop i
CSLibExt/Algorithms/Lean/DataStructures/SuffixArray.lean:54
Uses 2
DefinitionSuffix entries of a string#✓fully proved
For a list \(s = (s_0, \dots, s_{n-1})\) over \(\alpha\), let \(\hat s = (\mathrm{some}\,s_0, \dots, \mathrm{some}\,s_{n-1}, \mathrm{none})\) be its terminated string. The suffix entries of \(s\) are the list of pairs \((\hat s_{\ge i}, i)\) for \(i = 0, 1, \dots, n\) in increasing order, where \(\hat s_{\ge i}\) is \(\hat s\) with its first \(i\) entries removed: each nonempty suffix of \(\hat s\) paired with its starting index.
def suffixEntries (s : List α) : List (List (Option α) × Nat) :=
(List.range (s.length + 1)).map (fun i => ((terminated s).drop i, i))
def terminated (s : List α) : List (Option α) :=
s.map some ++ [none]
CSLibExt/Algorithms/Lean/DataStructures/SuffixTree.lean:60
Uses 1 · Used by 6
TheoremTerminated suffixes are distinct#✓fully proved
Let \(s\) be a list over \(\alpha\). The lists obtained from the terminated string of \(s\) by removing its first \(i\) symbols, for \(i\) ranging over \(0, 1, \ldots, |s|\), are pairwise distinct.
They are distinct because their lengths differ.
theorem nodup_terminated_drops (s : List α) :
((List.range (s.length + 1)).map (fun i => (terminated s).drop i)).Nodup
def terminated (s : List α) : List (Option α) :=
s.map some ++ [none]
CSLibExt/Algorithms/Lean/DataStructures/SuffixTree.lean:60
Uses 1 · Used by 2
DefinitionSuffix tree#✓fully proved
For a list \(s = (s_0, \dots, s_{n-1})\) over \(\alpha\), let \(\hat s = (\mathrm{some}\,s_0, \dots, \mathrm{some}\,s_{n-1}, \mathrm{none})\) be its terminated string over \(\mathrm{Option}\,\alpha\). The suffix tree of \(s\) is the radix trie with keys over \(\mathrm{Option}\,\alpha\) and natural-number values obtained from the empty trie by inserting, for \(i = n, n - 1, \dots, 0\) in this order, the suffix of \(\hat s\) starting at index \(i\) with value \(i\).
def suffixTree (s : List α) : RadixTrie (Option α) Nat :=
RadixTrie.buildFrom (suffixEntries s)
inductive RadixTrie (α : Type u) (β : Type v) where
| node : Option β → List (List α × RadixTrie α β) → RadixTrie α β
CSLibExt/Algorithms/Lean/DataStructures/RadixTrie.lean:42
def buildFrom {γ : Type u} {β : Type v} [DecidableEq γ] :
List (List γ × β) → RadixTrie γ β
| [] => empty
| (k, v) :: L => (buildFrom L).insert k v
CSLibExt/Algorithms/Lean/DataStructures/RadixTrie.lean:2315
def suffixEntries (s : List α) : List (List (Option α) × Nat) :=
(List.range (s.length + 1)).map (fun i => ((terminated s).drop i, i))
CSLibExt/Algorithms/Lean/DataStructures/SuffixTree.lean:81
Uses 3 · Used by 7
TheoremLookup of a suffix returns its starting index#✓fully proved
Let \(s\) be a list over \(\alpha\) and \(i\) a natural number with \(i \le |s|\). Looking up, in the suffix tree of \(s\), the terminated string of \(s\) with its first \(i\) symbols removed returns \(i\).
theorem lookup_suffix {s : List α} {i : Nat} (hi : i ≤ s.length) :
(suffixTree s).lookup ((terminated s).drop i) = some i
def suffixTree (s : List α) : RadixTrie (Option α) Nat :=
RadixTrie.buildFrom (suffixEntries s)
CSLibExt/Algorithms/Lean/DataStructures/SuffixTree.lean:127
def terminated (s : List α) : List (Option α) :=
s.map some ++ [none]
CSLibExt/Algorithms/Lean/DataStructures/SuffixTree.lean:60
Uses 6
TheoremLookup in the suffix tree returns starting indices#✓fully proved
Let \(s\) be a list over \(\alpha\), let \(k\) be a list over \(\alpha\) extended by a fresh terminator symbol, and let \(i\) be a natural number. If looking up \(k\) in the suffix tree of \(s\) returns \(i\), then \(i \le |s|\) and \(k\) is the terminated string of \(s\) with its first \(i\) symbols removed.
theorem eq_drop_of_lookup_suffixTree {s : List α} {k : List (Option α)} {i : Nat}
(h : (suffixTree s).lookup k = some i) :
i ≤ s.length ∧ k = (terminated s).drop i
def suffixTree (s : List α) : RadixTrie (Option α) Nat :=
RadixTrie.buildFrom (suffixEntries s)
CSLibExt/Algorithms/Lean/DataStructures/SuffixTree.lean:127
def terminated (s : List α) : List (Option α) :=
s.map some ++ [none]
CSLibExt/Algorithms/Lean/DataStructures/SuffixTree.lean:60
Uses 5
TheoremThe stored keys of a suffix tree are its terminated suffixes#✓fully proved
Let \(s\) be a list over \(\alpha\). A key \(k\) is stored in the suffix tree of \(s\) if and only if there is a natural number \(i \le |s|\) such that \(k\) is the terminated string of \(s\) with its first \(i\) symbols removed.
theorem mem_suffixTree_keys {s : List α} {k : List (Option α)} :
k ∈ (suffixTree s).keys ↔ ∃ i ≤ s.length, k = (terminated s).drop i
def suffixTree (s : List α) : RadixTrie (Option α) Nat :=
RadixTrie.buildFrom (suffixEntries s)
CSLibExt/Algorithms/Lean/DataStructures/SuffixTree.lean:127
def terminated (s : List α) : List (Option α) :=
s.map some ++ [none]
CSLibExt/Algorithms/Lean/DataStructures/SuffixTree.lean:60
Uses 7 · Used by 2
DefinitionStored keys of the suffix tree#✓fully proved
For a list \(s\) over \(\alpha\), the stored keys of \(s\) form the list of keys stored in the suffix tree of \(s\), in stored sibling order.
They are exactly the terminated suffixes. This concerns stored keys, not structural trie leaves: a valid radix trie may carry values at internal nodes, and no leaf characterization is claimed.
def storedKeys (s : List α) : List (List (Option α)) :=
(suffixTree s).keys
def suffixTree (s : List α) : RadixTrie (Option α) Nat :=
RadixTrie.buildFrom (suffixEntries s)
CSLibExt/Algorithms/Lean/DataStructures/SuffixTree.lean:127
Uses 2 · Used by 1
TheoremThe suffix tree stores one key per suffix#✓fully proved
For a list \(s\) over \(\alpha\), the list of stored keys of the suffix tree of \(s\) has length \(|s| + 1\).
There is one key for each terminated suffix.
theorem storedKeys_length (s : List α) : (storedKeys s).length = s.length + 1
def storedKeys (s : List α) : List (List (Option α)) :=
(suffixTree s).keys
CSLibExt/Algorithms/Lean/DataStructures/SuffixTree.lean:162
Uses 11
TheoremA tagged pattern cannot reach past the terminator#✓fully proved
For lists \(p\) and \(q\) over \(\alpha\), view their symbols in \(\alpha\) extended by a fresh terminator symbol. If \(p\) is a prefix of \(q\) followed by the terminator, then \(p\) is a prefix of \(q\).
The terminator differs from every symbol of \(\alpha\), so the pattern cannot reach past it.
theorem isPrefix_of_map_some_prefix_append_none {p q : List α} :
(p.map some) <+: (q.map some ++ [none]) → p <+: q
Used by 1
TheoremInfixes are prefixes of suffixes#✓fully proved
For lists \(s\) and \(p\), \(p\) is an infix (a contiguous sublist) of \(s\) if and only if there is a natural number \(i\) such that \(p\) is a prefix of the list obtained from \(s\) by removing its first \(i\) symbols.
theorem isInfix_iff_exists_isPrefix_drop {s p : List α} :
p <:+: s ↔ ∃ i, p <+: s.drop i
Used by 1
TheoremSuffix-tree search finds exactly the prefixes of suffixes#✓fully proved
For lists \(s\) and \(p\) over \(\alpha\), prefix search for \(p\) (each symbol viewed in the alphabet extended by the terminator) in the suffix tree of \(s\) succeeds if and only if there is a natural number \(i\) such that \(p\) is a prefix of the list obtained from \(s\) by removing its first \(i\) symbols.
theorem hasPrefix_suffixTree_iff_exists {s p : List α} :
(suffixTree s).hasPrefix (p.map some) = true ↔ ∃ i, p <+: s.drop i
def suffixTree (s : List α) : RadixTrie (Option α) Nat :=
RadixTrie.buildFrom (suffixEntries s)
CSLibExt/Algorithms/Lean/DataStructures/SuffixTree.lean:127
Uses 12 · Used by 1
TheoremSuffix-tree search finds exactly the infixes#✓fully proved
For lists \(s\) and \(p\) over \(\alpha\), prefix search for \(p\) (each symbol viewed in the alphabet extended by the terminator) in the suffix tree of \(s\) succeeds if and only if \(p\) occurs in \(s\) as a contiguous sublist (an infix).
theorem hasPrefix_suffixTree_iff_isInfix {s p : List α} :
(suffixTree s).hasPrefix (p.map some) = true ↔ p <:+: s
def suffixTree (s : List α) : RadixTrie (Option α) Nat :=
RadixTrie.buildFrom (suffixEntries s)
CSLibExt/Algorithms/Lean/DataStructures/SuffixTree.lean:127
Uses 4
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.