Optimal Structure for Prefix-Substring Queries
Abstract
The prefix-substring matching problem [Gu, Farach, and Beigel, SODA 1994] consists in preprocessing a string of length for the following queries: given a triple with , representing a prefix and a substring of , find the longest prefix of that is a suffix of . This is an useful primitive in e.g. dynamic text indexing, compressed pattern matching, and pattern matching on block graphs. The border tree uses some basic periodicity properties to answer such queries in time after time preprocessing of . We design a linear-space structure that answers such queries in constant time after time preprocessing of over a polynomial alphabet, which is worst-case optimal.
Keywords and phrases:
Border Tree, Prefix-Substring Query, Data StructuresCopyright and License:
2012 ACM Subject Classification:
Theory of computation Pattern matchingFunding:
Paweł Gawrychowski is partially supported by the Polish National Science Centre grant number 2023/51/B/ST6/01505. The work of Florin Manea and Jonas Richardsen was partly supported by the German Research Foundation (DFG) through the Heisenberg project 466789228 and the research project 562495345.Editors:
Philip Bille and Nicola PrezzaSeries and Publisher:
Leibniz International Proceedings in Informatics, Schloss Dagstuhl – Leibniz-Zentrum für Informatik
1 Introduction
It is usual for papers in the area of algorithms on strings to start with preprocessing the input string to support some standard queries. Gu, Farach, and Beigel [16] defined the following prefix-substring matching problem that consists in preprocessing a given string of length for the following queries: given with , representing a prefix and a substring of , find the longest prefix of that is a suffix of . The original motivation behind such queries was maintaining a dynamic indexing data structure. Using some basic periodicity properties, namely the fact that all borders of a given string of length at most can be decomposed into arithmetic progressions, the authors were able to design a data structure that answers prefix-substring queries in time after time preprocessing. Their structure has found quite a few other applications, for example it has been used in to design an efficient algorithm for pattern matching in LZW and LZ compressed texts [3, 10] to obtain algorithms working in and time, respectively (where is the size of the compressed representation, is the length of the text, and is the length of the pattern).
For pattern matching in both LZW and LZ compressed texts, Gawrychowski designed faster algorithms working in and time, respectively [14, 15]. The starting point in both results is an improved data structure for the related prefix-suffix matching problem, in which the query consists of , representing a prefix and a suffix of , and asks for detecting an occurrence of the whole in . A simple but useful observation is that such an occurrence corresponds to a long border of either or , where the long borders of are such that . By basic properties of periodicity, all long borders form a single arithmetic progression, which allows for answering such a query in constant time after time preprocessing. However, such a simple approach does not suffice to answer the more difficult prefix-substring queries in the same complexity, and both algorithms need to follow a more indirect route to achieve the improved time complexity: for LZW this requires amortizing the time complexity over the subsequent queries [14], and for LZ batching similar queries after an initial transformation of the input [15]. A later paper by Ganardi and Gawrychowski for pattern matching in SLP compressed texts [13] (which can be seen as a special case of LZ compression) avoids using prefix-substring queries altogether by, informally speaking, over-approximating the longest prefix with constantly many substrings of the pattern.
Pissis [19] observed that any data structure for answering longest common extension queries can be used to answer prefix-suffix queries. By plugging in the best known result, this results in a data structure with constant query time and preprocessing time, for a string of length over an integer alphabet . He also observed that such queries are very useful in pattern matching on node-labeled graphs, see e.g. [5, 8, 4, 2]).
Thus, the complexity of prefix-suffix queries is well understood. This is certainly not the case for prefix-substring queries, though, with the best bound being query after preprocessing [16]. While in the applications related to compressed pattern matching it was possible to avoid the extra factor of by exploiting the additional structure of the queries, this has led to certain technical complications that would best be avoided. Further, for the applications related to pattern matching on node-labeled graphs such additional structure of the queries is less clear. It would hence be desirable to design a structure with query time after linear time preprocessing. It is a priori not clear if such a structure exists: it may be the case that, say, prefix-substring matching is as difficult as predecessor search, leading to a lower bound of for structures of size .
We show how to answer prefix-substring queries in constant time with a structure of size that can be constructed in time for a string of length over a polynomial alphabet (which is a standard assumption in the area; otherwise, the construction time increases to due to sorting). We emphasise that, as observed in prior work, this allows for finding the longest prefix of that is a suffix of , for : we simply retrieve first the answer to the prefix-substring query , and then retrieve the answer to the query .
Our paper is structured as follows: we introduce the basic notions and data structures in Section 2, then give an overview of the considered problem and of our approaches in Section 3. In particular, we present a sequence of solutions for the problem, starting with simple ones (to set a baseline) and continuing with more involved and efficient ones (which, on the one hand, highlight potential obstacles one may meet when using certain techniques, and, on the other hand, provide us with deeper insights in the combinatorics of the problem), and conclude with the optimal solution. The technical details are presented in the rest of the paper (and in the appendix, for space reasons).
2 Preliminaries
Let be the set of strictly positive integer numbers and, for , let . For an alphabet , a string of length (over ) is a concatenation of characters with for . For , define for and otherwise (where is the unique string of length 0). We call a substring of and define to be the set of all substrings of . As a shorthand, we write and instead of and respectively, where denotes the length of . Furthermore, we define to be the mirror image of and, for , let be the string obtained by repeating exactly times.
Borders and periodicity.
For strings and with we say that is a prefix (respectively, suffix) of , if and only if (respectively, ); is a border of , if and only if it is both a prefix and a suffix of . We define , and as the sets of prefixes, suffixes and borders of respectively. For , we say that the prefix is the prior of the suffix and that the suffix is the posterior of the prefix .
Given some , we say that is -periodic, if and only if for all . Note that this is equivalent to the condition , meaning that is -periodic if and only if has a border of length . We say that the period of is the smallest value of such that is -periodic or if there is no such value. In the latter case, we also say that is aperiodic. The following lemma is well-known [18].
Lemma 1 (Periodicity lemma).
If a string of length is both -periodic and -periodic and , then is also -periodic.
Using this lemma, we can derive the following properties about borders and their periods. The proofs of these three results are given in Appendix A, for completeness.
Lemma 2.
Let be a string of length with and let such that is a border of with . Then and .
Lemma 3.
Let be a string of length . Then .
Let denote the set of borders of with period .
Lemma 4.
For string , with , and integer , the elements of form an arithmetic progression with step . For , contains at most one non-empty string.
Computational model.
We assume the standard unit-cost word RAM with logarithmic word-size (so each memory word consists of bits). Standard arithmetical and bitwise operations (and indirect addressing) on such words are assumed to take time [12]. We assume that our input is over a polynomial alphabet, i.e., , where is the length of the input string. We refer to a structure that can be stored in memory words as linear-space.
Longest common prefix.
For string , with , and , let be the length of the longest common prefix of and .
Lemma 5 ([17]).
Given a string of length , we can construct a linear-space data structure in time allowing us to answer queries for any in constant time.
Using this data structure, we can also find longest periodic prefixes. Given some , we can calculate , if we have and , meaning that is the longest -periodic prefix of . By constructing the data structure for , we can similarly determine longest common suffixes and longest periodic suffixes.
Suffix tree.
For some string of length , the suffix tree of is a compressed trie , i.e., a tree with the following properties:
-
Each edge is labeled with some non-empty string over the alphabet with being a special character.
-
The labels of any two edges starting at the same node do not share a common prefix.
-
Each inner node has at least two children.
Let be some node and let be the labels of the path from the root to . We now define as the set of strings corresponding to , for the root node it is . The defining property of the suffix tree is now that . We use the following results for the suffix tree:
Theorem 6 ([9]).
The suffix tree of a string , with , is constructed in time.
For any , there is exactly one node in the suffix tree of such that . We write and call the node corresponding to the substring .
Lemma 7 ([6]).
Given a string of length , we can construct a linear-space data structure in time allowing us to find for any in constant time.
We also use the following standard observation:
Observation 8.
Let be a string, let and be nodes in the suffix tree of and let and with (if this condition can be omitted). Then is a prefix of if and only if is an ancestor of .
In this paper, we take the relations “is ancestor of” and “is descendant of” to be reflexive, i.e., a node is both its own ancestor and its own descendant, unless explicitly noted otherwise.
The following result is shown in Appendix A.
Lemma 9.
Let be a string, let be a suffix of and be the node in the suffix tree of corresponding to . Then for all (this excludes all strings ending with ) and is the only suffix of corresponding to .
Border tree.
For some string of length , the border tree of is defined as follows. The nodes of the tree correspond one-to-one to the prefixes of and for any node corresponding to some prefix , the parent of is the node that corresponds to the longest border of . This is well defined, because always contains at least and any border of is a prefix of and therefore also a prefix of . The node corresponding to has no parent and is the root node of the tree. The border tree can now be compressed by grouping the borders by their periodicities (on each path). From Lemma 4 it follows that we can encode each group of borders as an arithmetic progression using constant space. The compressed border tree then has depth as seen in Lemma 3.
Lemma 10 ([16]).
Given a string of length , we can construct both the uncompressed and compressed border tree of in time.
From the definition of the border tree, it follows that for some prefix , the ancestors of the node corresponding to in the border tree correspond exactly to the borders of . For the compressed version of the border tree, this is not true anymore. Consider some section on some path, where all nodes correspond to prefixes with the same periodicity. During compression, this section is replaced with a single node. In this process, all nodes that were children of any node in the section become children of the new compressed node, even though they have different sets of ancestors. In particular, from the arithmetic progression of prefixes that is represented by their new parent, only the prefixes up to some length are actual borders. We can determine this length, for some node , by taking the smallest prefix associated with , the longest border of which has to have length , we can then trim the arithmetic progression corresponding to the parent of , removing all prefixes longer than this value.
Induced nodes and partner query.
Given two trees and , we can relate these trees to each other by using a common set of labels. Hereby, each label gets assigned to one node from each tree. We then say that two nodes and are induced, if and only if there are descendants of and of that share the same label. The partner of with respect to , denoted , is the lowest ancestor of , such that and are induced.
Lemma 11 ([1]).
Given trees and , we can construct data structures allowing us to compute for any in
-
time for any constant , for a linear-space data structure constructed in time.
-
time, for a data structure constructed in time and space.
Micro-macro decomposition.
Given a tree, we can decompose it, as follows. First, we select a subset of the nodes from the tree, including the root node. We call these nodes special. For each special node , we partition its children into non-empty sets. Each set of siblings corresponds to one fragment of the decomposition, containing the siblings, their parent (which becomes the root node of the fragment), and all their descendants which have as their lowest special ancestor. Since the root node is special, each node has a special ancestor and each non-special node belongs to exactly one fragment. Therefore, we obtain a set of micro-trees (the fragments) and a macro-tree that consists only of the special nodes, arranged as to preserve the ancestor/descendant relations between each pair of node. It is possible to construct such a decomposition for any desired fragment size efficiently (even though this is well known – see [11], for instance – we give a proof in Appendix A, fitting to our setting, for completeness):
Lemma 12.
Given a tree of size and some , it is possible to find a micro-macro decomposition that has fragments of size at most in time.
Other data structures.
We also use the following well known data structures.
Lemma 13 (RMQ [7]).
For and list of numbers , we can construct a linear-space data structure in time allowing us to retrieve for any in time.
Lemma 14 (Fusion tree [12]).
Given and sets such that, for every , , we can construct in time and space a data structure allowing us to determine the predecessor and successor of in any , i.e., and , for any in time.
3 Problem definition and overview of solution
Definition 15.
For string , with , we call , with , a prefix-substring query and denote by
the set of all queries111To focus on non-trivial prefix-substring queries, we exclude the case in this definition. This case is discussed at the end of Section 3.. For , we define
an element is a match for the query . Furthermore, we write
to refer to the length of the longest match. This is well-defined, since is always a match.
The problem PrefixSubstringQueries is now defined as follows: preprocess an input string such that we can answer prefix-substring queries for . For each given query , we need to return (in an online fashion, before reading the next query).
Note that the answer to PrefixSubstringQueries can be used to efficiently reconstruct the set of all matches, using the following property (proven in Appendix B):
Lemma 16.
For any string and any query , the answer satisfies
Consider now some element of . This is a suffix of . If , then is a suffix of and consequently, for all . Otherwise, it “crosses” over into , so it is not independent of . Let us formalize this notion:
Definition 17.
Let be a string and let be a query. Then we write
to denote the set of crossing matches and
to denote the set of non-crossing matches.
We also define and to be the lengths of the longest elements of and respectively. If the former is empty, we set .
We will solve PrefixSubstringQueries by separately finding the length of the longest crossing and the length of the longest non-crossing match, it is then . This is outlined in the following paragraphs.
Non-crossing matches.
Clearly, the non-crossing matches are exactly the borders of of length at most . Thus, determining the length of the longest non-crossing match, , is equivalent to determining the length of the longest such border of . Each such match satisfies that is a prefix of and a suffix of , so the longest match can then be found in the suffix tree of as the lowest ancestor of the node corresponding to , that corresponds to a suffix. Determining this is possible in time.
Crossing matches: simple solutions.
For crossing match , we can split the match at , such that is a suffix (and as such, a border) of and has prefix . We then say that induces the match . Like this, PrefixSubstringQueries can be rephrased as: “Find the longest border of such that its posterior starts with ”. By checking, for each border of individually, whether has prefix , we obtain a naive algorithm that answers queries in time, after time preprocessing. This can be optimized by exploiting the structure of the borders, yielding an algorithm with query time, after preprocessing.
Crossing matches: reduction to partner query.
Sticking with our approach to find the longest , such that is a border of and has prefix , we observe that this can be expressed as a problem on the border and suffix tree, as follows. Labeling the node corresponding to in the border tree and the node in the suffix tree with label for each , we then want to find the largest label such that the node labeled with in the border tree is an ancestor of the node corresponding to and the node labeled with in the suffix tree is a descendant of . This is quite similar to solving , only that the result of this query is only guaranteed to have a descendant with a label that also occurs in the descendants of , instead of having such a label itself. Still, it turns out that the matches are exactly the borders of of length at most , meaning that the longest match can be found similarly as the non-crossing matches. Apart from solving the partner query, this reduction only requires linear preprocessing and constant query time.
Crossing matches: final algorithm.
To obtain a constant time solution for crossing matches, we split the borders of into three groups:
-
For , the set of such satisfying that the posterior has prefix is an arithmetic progression with some step . We can find the longest such that induces a match by comparing the lengths of the longest -periodic suffixes of and for all such , using the fact that each has a different such length.
-
For and , we observe that the borders of with this condition only have a constant number of different periodicities. For each periodicity , we can in constant time determine the longest induced match, using the same method with which we optimized the initial naive algorithm.
-
For , we see that almost all (all, but the longest) prefixes with some shared periodicity share a common prefix of length and therefore, for each such periodicity , we only need to consider two candidates for inducing the longest match and in total, we consider candidates. If we sort them in the preorder of their respective posteriors in the suffix tree, all candidate prefixes that induce a match lie in some interval of this list, corresponding to the preorder interval representing the subtree rooted in . We can then find this interval using fusion trees and the longest match in the interval using an RMQ query.
While this enables us to answer queries in constant time, the last case requires maintaining -sized data structures for each prefix of . To avoid this, we perform a micro-macro decomposition of the border tree with fragment size and then only build these data structures for the prefixes corresponding to the special nodes. For some query , we find the fragment containing the node corresponding to and its special root . We then check all borders corresponding to ancestors of , using the method from above. The remaining borders of correspond to ancestors of in that fragment. The subset of these borders that induce a match can be expressed as an interval in 3D space, with the dimensions being the preorder and postorder indices of the corresponding nodes in the fragment and the preorder index of the posterior in the suffix tree. Since there are at most such borders, we can encode sets of borders in a constant number of machine words and use bit operations to operate on the sets. This allows for an time solution, using preprocessing per fragment, i.e., preprocessing time in total.
Combining this with Lemma 20, addressing non-crossing matches, we obtain the following.
Theorem 18.
For string , with , we can construct a linear-space data structure in time allowing us to determine for any in time.
Note that we only consider here queries with . In fact, our algorithm addressing non-crossing matches can be canonically used to answer queries , so the statement of Theorem 18 holds also for all queries of the form , with .
4 Non-Crossing Matches
Let us start with the non-crossing matches, which, as we will see, are the easier of the two kinds of matches. As hinted in the overview, it is
Therefore, the longest non-crossing match will be the longest border of of length at most . To find this, we use the following lemma, shown in Appendix D:
Lemma 19.
Given string , with , we can construct a linear-space data structure in time allowing us to determine for any in time.
Proof sketch.
We construct the suffix tree of . The desired solution satisfies that is the longest suffix of that is also a prefix of . In terms of the suffix tree, determining this corresponds to finding the lowest ancestor of that corresponds to a suffix of ; this ancestor can be precomputed for every node.
By setting , we obtain the following lemma.
Lemma 20.
For string , with , we can construct a linear-space data structure in time allowing us to determine for any in time.
5 Crossing Matches
Now let us turn to crossing matches, and begin with some simple solutions, which set a baseline for this problem. For a crossing match we can split the match at , such that is a suffix (and as such, a border) of and has prefix . As already defined in the overview, we then say that induces the match and try to find the longest border of such that its posterior starts with . Checking each border of individually yields a naive algorithm, answering queries in time after preprocessing (see Lemma 32 in Appendix).
We saw in Lemma 3 and Lemma 4 that can be partitioned into arithmetic progressions of borders. It turns out that we can check each of these progressions of borders in time (see Appendix E for the proof).
Lemma 21.
Let be a string of length . We can construct a linear-space data structure in time allowing us to find the largest satisfying and for any query and periodicity in constant time, provided we are given (an size representation of) as well.
Now it suffices to just check all groups of borders to find the solution (see Appendix E):
Lemma 22.
For string , with , we can construct a linear-space data structure in time allowing us to retrieve for in time.
5.1 Reduction to Partner Query
We can now focus on more efficient (yet not optimal) solutions. As derived previously, the problem can be phrased as finding the longest border of , such that the posterior has as a prefix. We can frame this problem in terms of the uncompressed border and suffix tree as follows: Consider the border and suffix trees for . For any , let be the node corresponding to and label both in the border tree and in the suffix tree with label . The necessary conditions on can now be expressed in terms of the suffix and border tree:
-
is a suffix/border of , if and only if the node labeled with in the border tree is an ancestor of the node corresponding to .
-
must have as a prefix, i.e., the node labeled with in the suffix tree must be a descendant of .
Therefore, the largest such can be determined by finding the lowest ancestor of in the border tree, labeled with some label , such that there is also a descendant of in the suffix tree with the same label. This can be reduced to a partner query.
Lemma 23.
If we can construct a data structure in time allowing to answer any partner query on two trees of size for some in time , then, given a string of length , we can create a data structure in time allowing us to determine for any query in time.
Proof.
See Figure 1 for an illustration of the proof.
During preprocessing, we construct the border and suffix tree, both labeled as described above, and data structures to answer partner queries on the trees and queries. We also construct the data structure necessary for Lemma 19.
When given a query , we initially determine the node in the border tree. The resulting node corresponds to some prefix . We know that and are induced, i.e, we can find a label such that there are descendants of each and with this label. More precisely, the node in the suffix tree and the node in the border tree are descendants of and respectively.
Consider now the label , representing the unknown solution, and the corresponding nodes and in suffix and border tree, respectively. We know that must be a descendant of , therefore, and are induced. Because the partner query finds the lowest induced ancestor, cannot be lower than on the path from the root to and it must be . Similarly, the solution must satisfy with .
Now, is an ancestor of both and , i.e., is a suffix of both and . Also, is a descendant of , i.e., has as prefix. As a consequence of these two facts, and share a common suffix of length . But then, (and, by extension, any match) must be a suffix (and consequently, a border) of . In particular, is the longest border of of length at most and we can determine using Lemma 19.
Using Lemma 11, we obtain:
Corollary 24.
Given a string , with , we can construct data structures allowing us to retrieve for in
-
time for , using a -sized structure, or
-
time, using a -sized structure.
5.2 Final algorithm
We will now present an algorithm to answer queries in time. We already have Lemma 20 for finding the length of the longest non-crossing match in constant time, so we again focus on crossing matches. In fact, let us subdivide further:
Definition 25.
For string , with , , and , we call a crossing match short, if and only if and long, otherwise. We denote by
and
the set of short and long crossing matches respectively.
Short crossing matches.
As before, each match corresponds to some with that satisfies and . Previously, we have been checking, for each border , whether its posterior has prefix , also making use of the structure that we found on borders. Now, we invert this procedure, we instead consider all suffixes with that have prefix and then we check, for each of them, if their prior is a border of . As it turns out, as for the borders of , the candidate suffixes also follow a structure that can be used to efficiently find our desired solution.
Lemma 26.
Let be a string and let be a substring of . Then
is an arithmetic progression and is -periodic with being the step of the progression (if the progression has more than one element).
Proof.
Let and let be the elements from the set. If there is only one element, we are done, so we assume now. For , define . Now for any ,
is a border or , therefore is -periodic. Let with for all . If , we have a progression with step and we are done. Otherwise, we can choose , and we have , by Lemma 1 we see that is -periodic which, due to minimality of , implies that divides . But now
is also -periodic and , i.e, also has prefix and it must be . As this holds for all , we are done.
Now consider some node in the suffix tree of and some string corresponding to that node. By Observation 8, the sets of suffixes starting with are exactly the suffixes that correspond to descendants of . Note that this includes a potential suffix corresponding to itself, since by Lemma 9, the suffix has length at least . As we can see, this set is independent from which we choose. We can make use of this fact, combined with the constant size representation that we have seen above, to efficiently precompute the candidate suffixes .
Lemma 27.
For string , with , we can construct a linear-space data structure in time allowing us to determine a constant size representation of for any in time.
Proof.
During preprocessing, we first construct a suffix tree for and some data structure allowing us to answer queries in constant time. Now we precompute the arithmetic progression for each node of the suffix tree, where is the longest element of .
This precomputation is done bottom-up. Any leaf node of corresponds to at most one suffix of , so creating the progression is trivial for these nodes. For some inner node with and children, we can compute the set in time , as follows. First, we copy the progressions of each child node, removing all elements in the process by pruning the length of the progression (note that the cutoff gets smaller as we move up the tree, so we never have to add any elements back). Then we merge the (disjoint) progressions of the child node. This can be done efficiently, since there will only be at most two non-empty progressions in total, and at most one with more than a single element.
We can see this by considering the resulting progression with some and (we assume , otherwise the claim is obviously true). For we have
since is the -th character of . Therefore, all but the last suffix in the progression share a common prefix of length and this prefix belongs to some child of . Consequently, the progression of this child contains all but (at most) one of the relevant suffixes.
Since each child has just a single parent, the total number of children (and similarly the required construction time) is .
Now, when we receive a query , we determine the node corresponding to and then return the arithmetic progression for after we removed all elements larger than . It remains to show how to use the structure of the suffixes to quickly find the longest match:
Lemma 28.
For string , with , we can construct a linear-space data structure in time allowing us to determine the length of the longest element of for any in time.
Proof.
See Figure 2 for an illustration of the proof.
In the preprocessing, we construct the data structure from Lemma 27, together with data structures for answering LCP queries on both and in time (see Lemma 5).
When we receive a query , we use the data structure from the previous lemma to determine for . We also remove from this progression all , as the prior must be a border of . Let be the resulting progression. If , we just check each element individually. In particular, is a suffix of , if and only if . Otherwise, we know that is -periodic and the same must hold for . Similar to Lemma 21, where each posterior started with a different number of repetitions of some string, here we can see that the lengths of the longest -periodic suffix of each potential match for are pairwise distinct. This helps us to find the longest match, by comparing these lengths to the length of the longest -periodic suffix of .
First, we determine, for all , the longest -periodic suffix of . This is done by determining the longest -periodic suffix of using an LCP query on , let be that suffix, . Now for any , the longest -periodic suffix of is : obviously, it is -periodic and cannot be -periodic, otherwise with and would also have to be -periodic, which contradicts our assumption about .
Next, we determine the length of the longest -periodic suffix of , it is . For this, we start by computing the length of the longest common suffix of and via an LCP query on . If , then and it is . Otherwise, we find the length of the longest -periodic suffix of . Since the last characters of and the first characters of are the same, we can extend this suffix by and obtain a -periodic suffix of . Consequently, .
Comparing these lengths, we have to consider two different cases. First, we consider the case , i.e., for every , the entire candidate is -periodic. If , then is exactly the -length suffix of , since both are -periodic and share the last characters. If , then it cannot be a suffix of by maximality of . Therefore, the largest with corresponds to our solution. If , and the longest -periodic suffixes of and do not match for some , then the former cannot be a suffix of the latter. If they were, they would have to share a common -periodic suffix of length , contradicting one of our assumptions about their longest -periodic suffixes. Therefore, we find the with and, if it exists, check if is a suffix of .
Long crossing matches.
Now, consider again the suffix tree and border tree. In Section 5.1 we have seen that for some to induce a match for the query , the must be a descendant of and the node corresponding to must be an ancestor of the node corresponding to in the border tree. We now label the nodes in the suffix tree in preorder, let be the label assigned to . We also label, for each , the node corresponding to in the border tree with .
Because we use preorder labels, the labels in any subtree of the suffix tree correspond to intervals. To find the longest match, we now need to determine the intersection of the interval corresponding to the subtree rooted in and all labels corresponding to ancestors of in the suffix tree. But the second set has size , thus this is not directly possible to do in constant time. In the previous section, we saw how we can find short crossing matches. For longer matches we can make use of the following property:
Lemma 29.
Let be a string of length and let with . Let . Then the posteriors share a common prefix of length .
Proof.
This means that for the posteriors of all but the longest element of either all have prefix , or none of them do. Therefore, since we are only interested in the longest border inducing a match, it suffices to only consider the labels of the longest two borders of . This allows us to make the set of labels small enough to achieve a constant query time, albeit using extra time during preprocessing:
Lemma 30.
For string , with , we can construct a data structure in time and space allowing us to retrieve for any in time.
Proof.
During preprocessing, we construct the suffix tree and, since we want to exploit the periodicity of the borders, the compressed version of the border tree. We assign labels to both trees as described above, but we only assign label to a node in the border tree, if is one of the two largest borders corresponding to that node and maintain a set containing all such values of . We also store, for each node of the suffix tree, the boundaries of the interval of labels for the subtree rooted in said node. For each node in the compressed border tree, we create a fusion tree containing all the labels on the ancestors of the node and a fusion tree containing the period of each ancestor (and, for each period value, a reference to the corresponding node). We also create a list , sorted by the values of and a data structure for answering RMQ-queries on this list (see Lemma 13). Since each node only has two labels and the compressed border tree has depth , both of these sets have size as well. Since we need to do this for all nodes, we require a total of time. We also construct the data structures from Lemmas 21 and 28.
When we receive a query , we start by determining , the corresponding label interval and the node corresponding to in the border tree. By finding the successor of and the predecessor of in , we see that and are exactly the boundaries of the interval in that contains values of corresponding to a match, namely . Using an RMQ-query, we can find the largest such .
By now, we only have checked all with . To check the rest, we start by finding the predecessor of in and the corresponding node (that has periodicity ). We then check this node using Lemma 21 in constant time and move up the tree, checking each node we encounter, until we reach a node corresponding to borders of length at most . This requires only a constant number of steps. Due to Lemma 2, the borders corresponding to have length at most and, in each step, the length of borders decreases by a factor of at least . The remaining borders can be checked using Lemma 28.
Reducing preprocessing time.
While we can now answer queries in constant time, this requires preprocessing time. In particular, we have to create, for each of the nodes in the border tree, a data structure of size . In order to reduce this it seems futile to try and reduce the size of each data structure to be constant. Instead, we achieve a better preprocessing time by computing the structure only for a subset of nodes. For this, we resort to a micro-macro decomposition of the compressed border tree. By then constructing the structure from the previous section only on the macro-tree, we can answer the query if corresponds to a special node. For a non-special node in some fragment , its ancestors can be decomposed into two sets: the ancestors of the root node of , which we can check in the same way, and the ancestors of the node in . For the latter set, checking it can be reduced to a range query, which, due to the small size of , turns out to be possible to answer in constant time.
Lemma 31.
For string , with , we can construct a linear-space data structure in time allowing us to retrieve for any in time.
Proof.
During preprocessing, we construct the data structure from Lemma 30, excluding the data structures specific to each node, i.e., , and (including the structure for answering RMQ-queries on ). We then create a micro-macro decomposition of the compressed border tree, consisting of fragments of size at most (see Lemma 12). For each of the special nodes, we create the -sized data structure from Lemma 30.
For each fragment of size , we now construct the following data structure. First, we associate each , where corresponds to some node of with a triple , where and are the preorder and postorder numbers of (in , not the entire tree) and is the preorder number of in the suffix tree (same as in the proof of the previous lemma). We then create a fusion tree for with being the lengths of all the relevant prefixes in , i.e., the longest two prefixes corresponding to each node of . We also construct a fusion tree for . Next, we precompute the following sets:
-
for all (in ascending order),
-
for all (in descending order),
-
for all (in ascending order),
-
for all (in descending order).
Each of these sets can be encoded using a number and thus, stored in two machine words, as follows. The set encoded by contains , if and only if the -th least significant bit of is set. If done in the order given above, each set can be constructed by adding one element to its predecessor, allowing for total construction time.
Hence, we construct data structures for each special node and fragment in time. As there are at most of those, constructing all data structures is done in time.
Given a query , we determine , the corresponding label interval and the node corresponding to in the border tree. We also find the fragment containing and its root node . We can use the data structure from Lemma 30 on to determine the longest border corresponding to an ancestor of that induces a match. The remaining borders of all correspond to ancestors of in the fragment, the lengths of the borders inducing a match is exactly
The first two dimensions ensure that the node corresponding to is an ancestor of and the last dimension ensures that the posterior has prefix . To determine , we start by finding the minimum and maximum element and of , which are the successor of and the predecessor of in respectively. is then the intersection of
-
,
-
,
-
and
-
.
Using bit operations, the bit representation of this intersection can be found in constant time and the same is true for the largest element in , this corresponds to the most significant bit set in the representation.
As described in the overview, this last lemma completes the proof of Theorem 18:
Theorem 18. [Restated, see original statement.]
For string , with , we can construct a linear-space data structure in time allowing us to determine for any in time.
References
- [1] Paniz Abedin, Sahar Hooshmand, Arnab Ganguly, and Sharma V. Thankachan. The heaviest induced ancestors problem: Better data structures and applications. Algorithmica, 84(7):2088–2105, 2022. doi:10.1007/S00453-022-00955-7.
- [2] Jarno N. Alanko, Davide Cenzato, Nicola Cotumaccio, Sung-Hwan Kim, Giovanni Manzini, and Nicola Prezza. Computing the LCP array of a labeled graph. In CPM, volume 296 of LIPIcs, pages 1:1–1:15. Schloss Dagstuhl – Leibniz-Zentrum für Informatik, 2024. doi:10.4230/LIPIcs.CPM.2024.1.
- [3] Amihood Amir, Gary Benson, and Martin Farach. Let sleeping files lie: Pattern matching in z-compressed files. J. Comput. Syst. Sci., 52(2):299–307, 1996. doi:10.1006/JCSS.1996.0023.
- [4] Rocco Ascone, Giulia Bernardini, Alessio Conte, Massimo Equi, Estéban Gabory, Roberto Grossi, and Nadia Pisanti. A unifying taxonomy of pattern matching in degenerate strings and founder graphs. In WABI, volume 312 of LIPIcs, pages 14:1–14:21. Schloss Dagstuhl – Leibniz-Zentrum für Informatik, 2024. doi:10.4230/LIPIcs.WABI.2024.14.
- [5] Jasmijn A. Baaijens, Paola Bonizzoni, Christina Boucher, Gianluca Della Vedova, Yuri Pirola, Raffaella Rizzi, and Jouni Sirén. Computational graph pangenomics: a tutorial on data structures and their applications. Nat. Comput., 21(1):81–108, 2022. doi:10.1007/S11047-022-09882-6.
- [6] Djamal Belazzougui, Dmitry Kosolobov, Simon J. Puglisi, and Rajeev Raman. Weighted ancestors in suffix trees revisited. In CPM, volume 191 of LIPIcs, pages 8:1–8:15. Schloss Dagstuhl – Leibniz-Zentrum für Informatik, 2021. doi:10.4230/LIPIcs.CPM.2021.8.
- [7] Michael A. Bender and Martin Farach-Colton. The LCA problem revisited. In LATIN, volume 1776 of Lecture Notes in Computer Science, pages 88–94. Springer, 2000. doi:10.1007/10719839_9.
- [8] Massimo Equi, Roberto Grossi, Veli Mäkinen, and Alexandru I. Tomescu. On the complexity of string matching for graphs. In ICALP, volume 132 of LIPIcs, pages 55:1–55:15. Schloss Dagstuhl – Leibniz-Zentrum für Informatik, 2019. doi:10.4230/LIPIcs.ICALP.2019.55.
- [9] Martin Farach. Optimal suffix tree construction with large alphabets. In FOCS, pages 137–143. IEEE Computer Society, 1997. doi:10.1109/SFCS.1997.646102.
- [10] Martin Farach and Mikkel Thorup. String matching in Lempel-Ziv compressed strings. Algorithmica, 20(4):388–404, 1998. doi:10.1007/PL00009202.
- [11] Greg N. Frederickson. A data structure for dynamically maintaining rooted trees. J. Algorithms, 24(1):37–65, 1997. doi:10.1006/JAGM.1996.0835.
- [12] Michael L. Fredman and Dan E. Willard. Surpassing the information theoretic bound with fusion trees. J. Comput. Syst. Sci., 47(3):424–436, 1993. doi:10.1016/0022-0000(93)90040-4.
- [13] Moses Ganardi and Pawel Gawrychowski. Pattern matching on grammar-compressed strings in linear time. In SODA, pages 2833–2846. SIAM, 2022. doi:10.1137/1.9781611977073.110.
- [14] Pawel Gawrychowski. Pattern matching in Lempel-Ziv compressed strings: Fast, simple, and deterministic. In ESA, volume 6942 of Lecture Notes in Computer Science, pages 421–432. Springer, 2011. doi:10.1007/978-3-642-23719-5_36.
- [15] Pawel Gawrychowski. Optimal pattern matching in LZW compressed strings. ACM Trans. Algorithms, 9(3):25:1–25:17, 2013. doi:10.1145/2483699.2483705.
- [16] Ming Gu, Martin Farach, and Richard Beigel. An efficient algorithm for dynamic text indexing. In SODA, pages 697–704. ACM/SIAM, 1994. URL: http://dl.acm.org/citation.cfm?id=314464.314675.
- [17] Toru Kasai, Gunho Lee, Hiroki Arimura, Setsuo Arikawa, and Kunsoo Park. Linear-time longest-common-prefix computation in suffix arrays and its applications. In CPM, volume 2089 of Lecture Notes in Computer Science, pages 181–192. Springer, 2001. doi:10.1007/3-540-48194-X_17.
- [18] M. Lothaire. Combinatorics on words, Second Edition. Cambridge mathematical library. Cambridge University Press, 1997.
- [19] Solon P. Pissis. Optimal prefix-suffix queries with applications. In SOSA, pages 166–171. SIAM, 2025. doi:10.1137/1.9781611978315.13.
Appendix A Proofs from Section 2
Lemma 2. [Restated, see original statement.]
Let be a string of length with and let such that is a border of with . Then and .
Proof.
We start by showing that . If we are done. Otherwise, as a substring of must also be -periodic and . Now if , then by Lemma 1, would be periodic and would have to divide . But then (which is -periodic itself), can be written as a repetition of and would be -periodic as well. Therefore, we have .
The longest border of (that is not itself) has length , i.e., .
Lemma 3. [Restated, see original statement.]
Let be a string of length . Then .
Proof.
Let be borders with and for all . Then by the previous lemma, we have , i.e., .
Lemma 4. [Restated, see original statement.]
For string , with , and integer , the elements of form an arithmetic progression with step . For , contains at most one non-empty string.
Proof.
Note that a substring of a periodic string has . In the case of the borders, this means that if we sort the borders by periodicity, the periodicity values will also be sorted. Consequently, the group of borders with the same periodicity occur in a sequence and, since the largest border (that is not itself) of some -periodic string is exactly shorter, the lengths of the group in the border form an arithmetic progression with step .
For , if there were two aperiodic borders with , then would also be a border of and would have period with , which is a contradiction.
Lemma 9. [Restated, see original statement.]
Let be a string, let be a suffix of and be the node in the suffix tree of corresponding to . Then for all (this excludes all strings ending with ) and is the only suffix of corresponding to .
Proof.
Assume we had with . By applying Observation 8 twice, we see that must correspond to a descendant of , and, since , must be a prefix of , which is a contradiction. The second part follows since the suffixes of have pairwise different lengths.
Lemma 12. [Restated, see original statement.]
Given a tree of size and some , it is possible to find a micro-macro decomposition that has fragments of size at most in time.
Proof.
We compute the fragments bottom-up the tree. For each node , we maintain the number of its descendants (including itself) that are not already part of some finished fragment and make sure that does not grow larger than . Initially, set for all leaf nodes .
For some inner node let be the set of its children. Partition this into singleton sets, i.e., . Maintain a set of all small partitions with . Merge the partitions by repeatedly combining two small partitions until there is at most one small partition left. We now have a set of partitions each smaller than . If there is only one partition , we set . If there is more than one partition, we make a special node and create a fragment for each of the partitions. Since other fragments will not contain any descendant of , we set . Note that we created fragments and at least of those contain at least non-special nodes. Therefore, our fragments contain on average non-special nodes and we cannot construct more than fragments.
Appendix B Proofs from Section 3
Lemma 16. [Restated, see original statement.]
For any string and any query , the answer satisfies
Proof.
For any element we have and . It follows that must both be a prefix and a suffix of , i.e., a border.
Any border of is both a prefix and a suffix of , therefore, by transitivity, both a prefix of and a suffix of , i.e., .
Appendix C Crossing matches: Naive algorithm
Lemma 32.
Given a string of length , we can construct a linear-space data structure in time allowing us to determine for any query in time.
Proof.
During preprocessing, we construct a border tree for and a data structure allowing us to answer LCP queries on in constant time (see Lemma 5).
To answer a query , we obtain all the borders of from the border tree (these correspond to ancestors of the node corresponding to ) and then check, for each border , whether its posterior has as a prefix. This is the case, if and only if . Since there are up to borders of , processing queries still requires linear time.
Appendix D Proofs from Section 4
Lemma 19. [Restated, see original statement.]
Given string , with , we can construct a linear-space data structure in time allowing us to determine for any in time.
Proof.
During preprocessing, we construct a suffix tree for . For each suffix of , we visit the corresponding node and mark it as a suffix node; note that each suffix corresponds to a different node as seen in Lemma 9.
We then traverse the suffix tree in preorder, maintaining a stack of suffix nodes on the path from the root to the current node we visit. Using this, we can, for each node, store a reference to its lowest ancestor that is a suffix node. We also construct the data structure that allows to answer queries (see Lemma 7).
When given a query , we determine , i.e., the node corresponding to in the suffix tree. Any is a suffix of , therefore, is a prefix of and a suffix of , and the corresponding node must be an ancestor of (by Observation 8) and a suffix node. Since we want to find the maximal value for , we take the lowest such ancestor and the corresponding suffix is our answer (if and the corresponding suffix is longer than , we use the lowest suffix node ancestor of the parent of instead). If there exists no such suffix node, we return zero instead.
Appendix E Proofs from Section 5
Lemma 21. [Restated, see original statement.]
Let be a string of length . We can construct a linear-space data structure in time allowing us to find the largest satisfying and for any query and periodicity in constant time, provided we are given (an size representation of) as well.
Proof.
During preprocessing, we construct a data structure allowing us to answer LCP queries on in constant time (see Lemma 5).
If , then there is only a constant number of borders, which we can check individually as seen in the previous section. Therefore, we focus on the case .
The lengths of borders form an arithmetic progression, i.e., there are such that . Due to periodicity, it is
and, for some , we can write and
Obviously, each of the posteriors starts with some repetition of and, for each of them, is repeated a different number of times. If we consider both and , we can see that the former must start with more repetitions of than the latter. Therefore, by computing we find the first mismatch between and . This tells us how many repetitions of are at the start of and, consequently, how many there are at the start of each of the posteriors. By comparing this number with the number of repetitions of at the start of , we can quickly decide which borders might induce a match. This is explained in detail now.
We can determine the number of repetitions at the start of as follows. Let us say that, as determined previously, starts with repetitions of . We now calculate .
If and , then consists only of repetitions of . Therefore, any of the borders whose posterior starts with at least repetitions of induces a match and, if there is a posterior starting with repetitions, the corresponding prior might induce a match (this can quickly be verified with another LCP query).
If (and ), then we know that starts with at least repetitions of . Since all the posteriors start with fewer repetitions of , there is no match in this case.
Otherwise, i.e., if and , we now that starts with exactly repetitions of . The only candidate for inducing a match is the border, whose posterior starts with exactly that amount of repetitions of (verified via LCP).
Lemma 22. [Restated, see original statement.]
For string , with , we can construct a linear-space data structure in time allowing us to retrieve for in time.
Proof.
During preprocessing, we construct a compressed border tree for and a data structure allowing us to answer LCP queries on in constant time (see Lemma 5).
Given a query , we start by locating the node corresponding to in the border tree. By moving up the tree, we can obtain representations of for all relevant values of and check each of them using Lemma 21 in constant time. As soon as we find some border inducing a match, we return its length.
