Suffix Balanced Tree
Definition
The order between suffixes is defined by lexicographical order. A Suffix Balanced Tree is a balanced tree that maintains the order of these suffixes, i.e., the suffix balanced tree of a string \(T\) is an ordered set of all suffixes of \(T\). A node in the suffix balanced tree corresponds to a suffix of the original string.
In particular, the in-order traversal of a suffix balanced tree yields the suffix array.
Construction Process
To build a suffix balanced tree for a string \(T\) of length \(n\), consider adding its suffixes in reverse order.
Let \(X\) be the set maintained by the suffix balanced tree, and let \(S\) be the suffix currently being added. Then adding the next suffix means inserting \(\texttt{c}S\) into \(X\) (which can also be understood as the suffix balanced tree maintaining the string \(S\), and the next step is to prepend a character \(\texttt{c}\) to \(S\)). This operation essentially inserts a node into the balanced tree.
Here, we use a balanced tree with expected height \(O(\log n)\), such as a Scapegoat Tree or Treap.
Method 1
During insertion, we compare the order between two suffixes by brute force to decide which subtree to go to. In this way, each insertion requires at most \(O(\log n)\) comparisons, and each comparison takes at most \(O(n)\) time, totaling \(O(n\log n)\).
Since there are \(n\) insertions, the time complexity of this method is bounded by \(O(n^2 \log n)\).
Method 2
Note that the only difference between \(\texttt{c}S\) and \(S\) is the character \(\texttt{c}\), and \(S\) already belongs to \(X\). This can be leveraged to optimize the insertion operation.
Suppose we want to compare the two strings \(\texttt{c}S\) and \(A\), where \(A, S \in X\). During each comparison, we first compare their first characters. If they differ, the order is determined. If they are equal, we only need to compare the order of the strings after removing the first character. Since both strings without their first character already belong to \(X\), we can use the \(O(\log n)\) ranking operation of the balanced tree to complete the comparison. Thus, each insertion takes at most \(O(\log^2 n)\).
Since there are \(n\) insertions, the time complexity of this method is bounded by \(O(n \log^2 n)\).
Method 3
According to Method 2, if we can compare the order between two nodes in the balanced tree in \(O(1)\) time, then the suffix balanced tree can be constructed in \(O(n \log n)\) time.
Let \(val_i\) denote the value of node \(i\). If during the construction of the balanced tree, each node maintains an additional tag \(tag_i\) such that \(tag_i > tag_j \iff val_i > val_j\), then we can determine the order between two nodes in \(O(1)\) based on \(tag_i\).
Let each node in the balanced tree correspond to a real interval, and let the root correspond to \((0, 1)\). For node \(i\), denote its corresponding real interval as \((l, r)\). Then \(tag_i = \frac{l + r}{2}\), its left subtree corresponds to \((l, tag_i)\), and its right subtree corresponds to \((tag_i, r)\). It is easy to verify that \(tag_i\) satisfies the above requirement.
Since we use a balanced tree with expected height \(O(\log n)\), the precision is guaranteed to some extent. In practice, a larger interval can be used, e.g., letting the root correspond to \((0, 10^{18})\).
Method 4
We can first construct the suffix array, and then build the suffix balanced tree based on the suffix array. The complexity bottleneck of this approach lies in the construction of the suffix array or the complexity of inserting \(n\) elements into the balanced tree at once.
Deletion Operation
Suppose the currently added suffix is \(\texttt{c}S\), and the previously added suffix is \(S\). The suffix balanced tree also supports deleting the suffix \(\texttt{c}S\) (which can be understood as the suffix balanced tree maintaining the string \(\texttt{c}S\), and deleting the leading \(\texttt{c}\)).
Similar to the insertion operation, the deletion of \(\texttt{c}S\) can be accomplished using the node deletion operation of the balanced tree.
Advantages of Suffix Balanced Trees
- The idea behind suffix balanced trees is relatively clear and easier to understand compared to other suffix structures like suffix automata. If you can implement a balanced tree, you can implement a suffix balanced tree.
- The complexity of suffix balanced trees does not depend on the size of the character set.
- Suffix balanced trees support deleting a character from the beginning of the string.
- If a persistent balanced tree is used, the suffix balanced tree can also be made persistent.
Example Problems
P3809【Template】Suffix Sorting
A template problem for suffix arrays. After constructing the suffix balanced tree, obtain the suffix array via in-order traversal.
Reference Code (SGT Version)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | |
P6164【Template】Suffix Balanced Tree
Problem Statement
Given an initial string \(s\) and \(q\) operations:
- Append several characters to the end of the current string.
- Delete several characters from the end of the current string.
- Ask how many times the string \(t\) appears as a contiguous substring in the current string?
The problem is forced online. The total length of string changes and the initial length \(\le 8 \times 10^5\), \(q \le 10^5\), and the total length of all queries \(\le 3 \times 10^6\).
For operations 1 and 2, since suffix balanced trees conveniently support prepending and deleting from the beginning, we consider converting tail insertion and tail deletion into head insertion and head deletion. Here, if we maintain the suffix balanced tree of the reversed string of \(s\) instead of \(s\) itself, we can achieve this conversion. Adding and deleting in the balanced tree take \(O(\log n)\) each, so adding or deleting a character takes \(O(\log n)\). Let \(N\) be the total number of characters added or deleted. Then the total time complexity for this part is \(O(N \log n)\).
For operation 3, the number of occurrences of \(t\) equals the number of suffixes that have \(t\) as a prefix. The number of suffixes with \(t\) as a prefix equals the rank of its successor minus the rank of its predecessor. By appending a very large character to \(t\), we can construct a successor of \(t\). By decreasing the last character of \(t\) by 1, we can construct a predecessor of \(t\).
Now, to query the rank of a string \(t\) in the suffix balanced tree, since we cannot guarantee that \(t\) appears in the suffix balanced tree, we can only compare string sizes by brute force each time. A single comparison takes \(O(|t|)\) time, and each query requires at most \(O(\log n)\) comparisons, so the complexity per query is \(O(|t|\log n)\). Let \(L\) be the total length of all query strings. Then the total time complexity for this part is \(O(L \log n)\).
Reference Code (SGT Version)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | |
References
- Chen Lijie - "Applications of Weight-Balanced Trees and Suffix Balanced Trees in Informatics Olympiads"
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:OI-wiki
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用