Efficiently computing runs on a trie
Ryo Sugahara, Yuto Nakashima, Shunsuke Inenaga, Hideo Bannai, Masayuki, Takeda

TL;DR
This paper introduces an efficient method to compute and bound the number of runs in tries, a type of rooted edge-labeled tree, with a new algorithm achieving near-linear time complexity.
Contribution
The paper establishes an upper bound on the number of runs in tries and presents an $O(n \log \log n)$ time algorithm for their enumeration.
Findings
Number of runs in a trie is less than the number of edges.
Asymptotic lower bound on maximum run density in tries is approximately 0.993238.
Proposed algorithm runs in $O(n \log \log n)$ time and uses $O(n)$ space.
Abstract
A maximal repetition, or run, in a string, is a maximal periodic substring whose smallest period is at most half the length of the substring. In this paper, we consider runs that correspond to a path on a trie, or in other words, on a rooted edge-labeled tree where the endpoints of the path must be a descendant/ancestor of the other. For a trie with edges, we show that the number of runs is less than . We also show an asymptotic lower bound on the maximum density of runs in tries: where is the maximum number of runs in a trie with edges. Furthermore, we also show an time and space algorithm for finding all runs.
Peer Reviews
No public reviews on file for this paper yet. If you reviewed it on a platform where reviews are public (OpenReview, ICLR, NeurIPS, ICML), you can paste yours below so the community can read it here.
Videos
No videos yet. Explain this paper in a talk, walkthrough, or lecture? Add one.
Taxonomy
TopicsAlgorithms and Data Compression · DNA and Biological Computing · semigroups and automata theory
Efficiently computing runs on a trie
Ryo Sugahara
Yuto Nakashima
Shunsuke Inenaga
Hideo Bannai
Masayuki Takeda
Department of Informatics, Kyushu University, Japan
PRESTO, Japan Science and Technology Agency
M&D Data Science Center, Tokyo Medical and Dental University, Japan
Abstract
A maximal repetition, or run, in a string, is a maximal periodic substring whose smallest period is at most half the length of the substring. In this paper, we consider runs that correspond to a path on a trie, or in other words, on a rooted edge-labeled tree where the endpoints of the path must be a descendant/ancestor of the other. For a trie with edges, we show that the number of runs is less than . We also show an asymptotic lower bound on the maximum density of runs in tries: where is the maximum number of runs in a trie with edges. Furthermore, we also show an time and space algorithm for finding all runs.
keywords:
maximal repetitions, Lyndon words, trie
††journal: Theoretical Computer SCience
1 Introduction
Repetitions are fundamental characteristics of strings, and their combinatorial properties as well as their efficient computation has been a subject of extensive studies. Maximal periodic substrings, or runs, is one of the most important types of repetitions, since they essentially capture all occurrences of consecutively repeating substrings in a given string. One of the reasons which makes runs important and interesting is that the number of runs contained in a given string of length is [1], in fact, less than [2], and can be computed in time [1, 3]. Note that the total number of occurrences of squares in a string can be , or for only primitive squares.
In this paper, we consider runs that correspond to a path on a trie, or in other words, on a rooted edge-labeled tree where the endpoints of the path must be a descendant/ancestor of the other. The contributions of this paper are threefold. For a trie with edges, we show:
Upper bound: , where is the maximum number of runs in a trie with edges.
- 2.
Lower bound: .
- 3.
Algorithm: time and space algorithm for computing all runs in a trie, assuming an integer alphabet.
A preliminary version of this paper which described an time and space algorithm appeared in [4]. The running time has been improved to . This paper also gives tighter lower bounds than in [4].
1.1 Related Work
A similar problem was considered in [5, 6, 7], but differs in three aspects: they consider distinct repetitions with integer powers on an unrooted (or undirected) tree. In this work, we consider occurrences of repetitions with maximal (possibly fractional) powers on a rooted (or directed) tree.
Funakoshi et al. [8] show how to compute all maximal palindromes and all distinct palindromes in tries, in time, where is the height of the trie. Interestingly, the upper bound on the number of maximal palindromes and distinct palindromes in a trie are also known to be , but a linear time algorithm has not yet been discovered.
2 Preliminaries
2.1 Strings, Periods, Maximal Repetitions, Lyndon Words
Let denote the alphabet. We consider an integer alphabet, i.e., for some constant . is the set of strings over . For any string , let denote the th symbol of , and the length of . For any , let . For technical reasons, we assume that is followed by a distinct character (i.e. ) in that does not occur in .
A string is primitive, if it is not a concatenation of 2 or more complete copies of the same string. A string , for some string , is called a square, and in particular, if is primitive, then is called a primitively rooted square. An integer is called a period of , if for all . The smallest period of will be denoted by . For any period of , there exists a string , called a border of , such that and for some . A string is a repetition, if its smallest period is at most half the length of the string. A maximal repetition, or run, is a maximal periodic substring that is a repetition, i.e., a maximal repetition of a string is an interval of positions where , and for any and such that or . In other words, a run contains at least two consecutive occurrences of a substring of length , and the periodicity does not extend to the left or right of the run. The smallest period of the run will be called the period of the run. The fraction is called the exponent of the run.
Let denote an arbitrary total ordering on , as well as the lexicographic ordering on induced by this ordering. We also consider the reverse ordering on (i.e., ), and the induced lexicographic ordering on . For , let . A string is a Lyndon word w.r.t. to a given lexicographic ordering, if is lexicographically smaller than any of its proper suffixes. A well known fact is that a Lyndon word cannot have a non-empty proper border, since a non-empty proper border of a word is a suffix that is lexicographically smaller than the word itself.
Crochemore et al. observed that in any run with period , and any lexicographic ordering, there exists a substring of length in the run, that is a Lyndon word [9, 10]. Such Lyndon words are called L-roots. Below, we briefly review the main result of [2] which essentially tied longest Lyndon words starting at specific positions within the run, to L-roots of runs. This will be the basis for our new results for tries.
Lemma 1** (Lemma 3.2 of [2])**
For any position of string , let be such that for . Then, the longest Lyndon word that starts at position is w.r.t , and for some w.r.t. .111Note that becomes when .
Lemma 2** (Lemma 3.3 of [2])**
Let be a run in with period , and let be such that . Then, any L-root of with respect to is the longest Lyndon word with respect to that is a prefix of .
Since an L-root cannot be shared by two different runs, it follows from Lemma 2 that the number of runs is at most , since each position can be the starting point of at most two L-roots that correspond to distinct runs. In [2], a stronger bound of was shown from the observation that each run contains at least one L-root that does not begin at the first position of the run, and that the two longest Lyndon words starting at a given position for the two lexicographic orders cannot simultaneously be such L-roots of runs. This is because if and were L-roots and the runs start before position , then, from the periods of the two runs, it must be that contradicting that is a Lyndon word and cannot have a non-empty border. In Section 3.1, we will see that the last argument does not completely carry over to the case of tries, but show that we can still improve the bound again to .
The above lemmas also lead to a new linear time algorithm for computing all runs, that consists of the following steps:
compute the longest Lyndon word that starts at each position for both lexicographic orders and , 2. 2.
check whether there is a run for which the longest Lyndon word corresponds to an L-root.
There are several ways to compute the first step in amortized constant time for each position, but it can essentially be reduced to computing the next smaller values (NSV) in the inverse suffix array of the string. We describe the algorithm in more detail in Section 3.2, and will see that the amortization of the standard algorithm does not carry over to the trie case. We give a new linear time algorithm using the static tree set-union data structure (more specifically, decremental nearest marked ancestor queries) [11], which does carry over to the trie case.
The second step can be computed in constant time per candidate L-root with linear time-preprocessing, by using longest common extension queries (e.g. [12]) in the forward and reverse directions of the string. Unfortunately again, this does not directly carry over to the trie case because, as far as we know, longest common extension queries on trees can be computed in constant time only in the direction toward the root of the trie, when space is restricted to linear in the size of the trie. We show that the longest common extension query in the opposite direction can be reduced to what are called path-tree LCE queries [13]. A naive application of this data structure results in an time and space algorithm. In Section 3.3, we will show how to adapt the method of [13] so that a batch of path-tree LCE queries can be computed in total time.
2.2 Common Suffix Trie
A trie is a rooted tree with labeled edges, such that each edge to the children of a node is labeled with distinct symbols. A trie can be considered as representing a set of strings obtained by concatenating the labels on a root to leaf path. Note that for a trie with edges, the total length of such strings can be quadratic in . An example can be given by the set of strings where is an arbitrary string and are pairwise distinct characters. Here, the size of the trie is , while the total length of strings is . Also notice that the total number of distinct suffixes of strings in is also . However if we consider the strings in the reverse direction, i.e., consider edges of the trie to be directed toward the root, the number of distinct suffixes is linear in the size of the tree. Such tries are called common suffix tries [14]. We will use the terms parent/child/ancestor/descendant with the standard meaning based on the undirected trie, e.g., the root is an ancestor of all nodes in the trie. For any node of the trie, will denote its parent node. For any integer , denotes the -th ancestor of , i.e. . Note that a trie can be pre-processed in linear time so that for any node and integer , can be computed in constant time (e.g. [15]).
For any nodes of the trie where is an ancestor of , or vice versa, let denote the path from to , and let denote the string obtained by concatenating the labels on . For technical reasons, we assume that the root node has an auxiliary parent node , where the edge is labeled by a distinct character in that is not used elsewhere in the trie. We denote by the string obtained by concatenating the labels on the path , i.e., . Such strings will be called a suffix of the trie.
3 Runs in a Trie
3.1 The Number of Runs in a Trie
We first define runs on a trie. Let be an ancestor of . A path is a run on a trie if is a repetition and is maximal. More precisely, , and for any descendant of and ancestor of , if or . Let denote the maximum number of runs in a trie with edges.
Noticing that the parent of any node in the trie is unique, it is easy to see that analogies of Lemmas 1 and 2 hold for tries. Thus, we have the following.
Corollary 3
For any node except the root or , let be such that for . Then, the longest Lyndon word that is a prefix of is w.r.t. and w.r.t. for some .
Corollary 4
Let be a run with period in the trie and be such that , where . Then, any L-root of the run with respect to is the longest Lyndon word that is a prefix of .
Since we assumed that the edge labels of the children of a given node in a trie are distinct, a given L-root can only correspond to one distinct run; i.e., the extension of the period in both directions from an L-root is uniquely determined. Therefore, the argument for standard strings carries over to the trie case, and it follows that the number of runs must be less than . We further observe the following
Theorem 5
.
Proof 1
Suppose and are simultaneously L-roots of runs respectively w.r.t. and , and that they do not start at the beginning of the runs. Let . If has only one child, this leads to a contradiction using the same argument as the case for strings; i.e., if is the child of , then, from the periods of the two runs, contradicting that is a Lyndon word and cannot have a non-empty border. Thus, must have at least two children, , where and . Let be the number of branching nodes in the trie. Then, the number of leaves is at least . Since a run cannot start before a leaf node, this means that a longest Lyndon word starting at a leaf cannot be an L-root that does not start at the beginning of the run. Therefore, although there can be at most nodes such that both longest Lyndon words are such L-roots, there exist at least nodes where both are not. Thus, the theorem holds.
In a similar way to Theorem 3.6 of [2], we can bound the sum of exponents of all runs in a trie.
Corollary 6
The sum of exponents of all runs in a trie with edges is less than .
Proof 2
A given run with exponent contains at least occurrences of its L-roots that do not start at the beginning of the run, each corresponding to a longest Lyndon word starting at that position. From the proof of Theorem 5, the total number of these L-roots is less than . Let denote the set of all runs in the trie. Then, , and the Corollary follows.
Next, we consider lower bounds. Since a string can be considered as a special case of a trie with no branching nodes, lower bounds on strings directly carries over to tries. The best known lower bound for strings is [16]. However, we can improve this bound for tries with the following idea: given a run-rich (binary) string, consider an occurrence of substring bab. If we add a branching edge labeled with a as a child of a, we can create a new run aa. Since this creates at least one new run with a single new edge, we increase the overall ratio of runs. This can be done for occurrences of aba as well (by adding b), and as many times as possible.
Using the run-rich string t184973 available at [17], we can construct a trie that contains runs with edges (more precisely, there were positions where adding an edge resulted in 1 new run, and positions that resulted in 2 new runs). By simply concatenating the string t184973 times (with a delimiter in between) and constructing the trie for each copy (and connecting them), we can obtain a trie with runs and edges. For any length that is not a multiple of , let . Then, since it is possible to add arbitrary edges to a given trie without reducing the number of runs, there exists a trie with at least runs with edges. Thus,
[TABLE]
Since as , we have .
Theorem 7
.
Note that our aim here was to demonstrate that tries with edges can contain more runs than strings of length . A more careful application of the above idea will most certainly lead to better lower bounds.
3.2 Computing Longest Lyndon Words
Next, we consider the problem of computing, for any node of the trie, the longest Lyndon word that is a prefix of . We first describe the algorithm for strings, which is based on the following lemma.
Lemma 8
For any string and position , the longest Lyndon word starting at w.r.t. is , where is such that .
Proof 3
Let . By definition, we have for any . For any such , . If the longest common prefix of and is longer than or equal to , this implies , a contradiction. Therefore, the longest common prefix of and must be shorter than , implying that . Thus, is a Lyndon word. Suppose is a Lyndon word for some . Then, . Since , cannot be a prefix of which implies , contradicting the definition of . Thus, is the longest Lyndon word starting at .
From Lemma 8, the longest Lyndon word starting at each position of a string can be computed in linear time, given the inverse suffix array of . The inverse suffix array of is an array of integers such that when is the lexicographically th smallest suffix of . That is, the in Lemma 8 can be restated as . This can be restated as the problem of finding the next smaller value (NSV) for each position of the , for which there exists a simple linear time algorithm (e.g. [18]) as show in Algorithm 1.
The linear running time can be shown with a simple amortized analysis; in the while loop, is only accessed once for any position since is set to a larger value and thus will subsequently be skipped.
Since, as before, the parent of a node is unique, Lemma 8 carries over to the trie case. We can assign the lexicographic rank of to each node in linear time from the suffix tree of the trie, which is a compacted trie containing all and only suffixes of the trie.
Theorem 9** (suffix tree of a trie [14, 19])**
The suffix tree of a trie on a constant or integer alphabet can be represented and constructed in time.
The problem now is to compute, for each node , the closest ancestor of such that the lexicographic rank of is smaller than that of . Algorithm 1 can be modified to correctly compute the values on the trie; the for loop is modified to enumerate nodes in some order such that the parent of a considered node is already processed, and line 1 can be changed to . However, the amortization will not work; the existence of branching paths means there can be more than one child of a given node, and the same position (node) could be accessed in the while loop for multiple paths, leading to a super-linear running time.
To overcome this problem, we introduce a new, (conceptually) simple linear time algorithm based on nearest marked ancestor queries.
Theorem 10** (decremental nearest marked ancestor [11])**
A given tree can be processed in linear time such that all nodes are initially marked, and the following operations can be done in amortized constant time:
: return the nearest ancestor node of that is marked.
- 2.
: un-mark the node .
The pseudo-code of our algorithm is shown in Algorithm 2.
Theorem 11
Given a trie of size , the longest Lyndon word that is a prefix of for each node can be computed in total time and space.
Proof 4
It is easy to see the linear running time of Algorithm 2. The correctness is also easy to see, because the nodes are processed in decreasing order of lexicographic rank, and thus, all and only nodes with larger lexicographic rank are unmarked.
3.3 Computing Runs
To compute all runs in a trie, we extend the algorithm for strings to the trie case. After computing the longest Lyndon word that is a prefix of for each node for the two lexicographic orderings and , we must next see if they are L-roots of runs by checking how long the periodicity extends. Given a longest Lyndon word w.r.t. that starts at , we can compute the longest common extension from nodes and towards the root, i.e., the longest common prefix between and . To avoid outputting duplicate runs, we will process only the left-most (deepest) L-root of each run. This can be done by processing the L-roots from the leaves. Whenever , this implies that the longest Lyndon word starting at is also , so we mark node as not being the left-most L-root for . Using the suffix tree of the trie, this longest common extension query can be computed in constant time after linear time preprocessing, since it amounts to lowest common ancestor queries (e.g. [20]). The central difficulty of our problem is in computing the longest common extension in the opposite direction, i.e. towards the leaves, because the paths can be branching. We cannot solve this problem by simply considering longest common extensions on the common suffix trie for the reverse strings, since, as observed in Section 2, this can lead to a quadratic blow-up in the size of the trie.
LCE queries on tries in the leaf direction, called path-tree queries, were considered by Bille et al. [13]. In a path-tree LCE query, we are given a path , where is an ancestor of , and a node and are asked to return the longest common prefix between and any path from to a descendant leaf. For technical reasons, we will represent the above path-tree LCE query as , i.e., we represent the path with its length and deeper end . The output of the query is the node that is a descendant of such that is the longest common prefix.
Bille et al. showed the following result:
Theorem 12** (Theorem 2 of [13])**
For a tree T with n nodes, a data structure of size can be constructed in time to answer path–tree LCE queries in time.
In our case, for each (deepest) L-root 222We write here, since its reverse is not a Lyndon word to be processed, we simply call one path-tree LCE query , as we know this value will be less than . Since there are candidate L-roots, the computation can be done in total time.
Finally, we show that this can be reduced to total time since all the queries are known in advance, and Bille et al.’s approach can be modified to process a batch of queries more efficiently.
Our algorithm closely follows the approach of [13]. For any query , their approach iteratively reduces the query to another query with equivalent output, such that becomes smaller compared to . More precisely, they show:
Lemma 13** (Lemma 4 in [13])**
For a tree T with n nodes and a parameter b, a data structure of size can be constructed in time333In the original paper, the statement is time, but is apparently a typo. time, so that given a path of length ending at and a subtree rooted at we can reduce the query in time so that the path is of length at most .
A weaker version of Theorem 12 where the size and construction time is can be obtained by building and applying the data structure of Lemma 13 times for . In our case, we process a batch of queries for each value of so the total space usage can be suppressed to . To achieve total running time, we shall prove the following Lemma. Note that the main difference is essentially in that while the original approach answered predecessor/successor queries for each tree-path query using predecessor/successor data structures (thus requiring an extra factor of ), we are able to answer them by sorting the data and all of the tree-path queries at once using radix sort.
Lemma 14
For a tree T with n nodes, and parameter b, a set
[TABLE]
of path-tree LCE queries with can be reduced to a set
[TABLE]
of queries such that and for in time.
The queries are processed as follows: The first step is to determine whether the length of the LCE is less than or not for all . To do this, we assign new names (i.e., integers of size ) to all distinct paths of length in the trie. This can be done in time using Theorem 9. Let
[TABLE]
where is the name assigned to the length path from to . For path-tree query , let , that is, is the name assigned to the length prefix of the query path. Then, it is not difficult to see that the length of the LCE is at least if and only if for some , and in such case, we have . We can determine such , if it exists, in total time for all as follows. Let
[TABLE]
and sort the set (assuming is larger than any node) in time by radix sort. Then, if it exists, must be the largest element in that precedes element . This can also be computed for all in total time by simple scans on the sorted set.
For queries such that the length of the LCE is less than , we can simply choose , , and . Otherwise, let , , and . It is clear we have . If , then we can simply use , , and . If , we further reduce the query using difference covers for trees, similarly to what was done in Lemma 13, described below.
Lemma 15** (Lemma 1 and Remark of [13])**
For any tree with nodes and a parameter , it is possible to mark nodes of T, so that for any two nodes at (possibly different) depths at least , there exists such that the -th ancestors of both and are marked. Furthermore, such can be calculated in time and the set of marked nodes can be determined in time. Also, if a node is marked, so are all its descendants at distance , and if the depth of the node is at least , so is its -th ancestor at distance.
We use Lemma 15 for , and further modify the queries so that we can start the LCE at marked nodes: i.e., for all such that , , , , where can be obtained in time for each query. Consider all paths (called canonical paths) whose length is a multiple of and end (and consequently start) at a marked node. Since any path has length at most length , there can be up to canonical paths that end at a given node. Since there are marked nodes, there are at most canonical paths. As was done for length paths, we rename all length paths using a suffix tree in time. Then, if we consider canonical paths as sequences of these names, the total length for all canonical paths is since each of them has length at most . Thus, we can sort all (renamed) canonical paths in time (e.g. Lemma 8.7 of [21]). We can also compute in total time, the longest common prefix between lexicographically adjacent (renamed) canonical paths, and a range minimum query data structure so that the longest common prefix between any two (renamed) canonical paths can be computed in constant time. Let
[TABLE]
where is the lexicographic rank of the canonical path . For any query that is left, let be the lexicographic rank of the longest (renamed) canonical path that is a prefix of . Let
[TABLE]
We can sort in time using radix sort. Then, for each element , either its predecessor or successor (which can be computed in total time for all of them by simple scans on the sorted set), will have the longest common prefix, provided that . This can be computed in constant time each using range minimum queries. Since we have computed the longest common extension where each character (name) represents a length substring, the remaining length of the LCE is at most .
From the above arguments, we have proved Lemma 14 and obtain the following.
Theorem 16
For a tree T with n nodes, a batch of tree-path LCE queries can be computed in total time.
4 Conclusion
We generalized the notion of runs in strings to runs in tries, and showed that the analysis of the maximum number of runs, as well as algorithms for computing runs can be extended and adapted to the trie case, but with a slight increase in running time.
Our algorithm can output all primitively rooted squares in time, which is tight, since there can be primitively rooted squares in a string, e.g., Fibonacci words [22], and thus in a trie.
An obvious open problem is whether there exists a linear time algorithm for computing all runs in a trie. For strings, there exists another linear time algorithm for computing all runs that is based on the Lempel-Ziv parsing [1]. It is not clear how this algorithm could be extended to the case of tries. The case for general ordered alphabets, instead of integer alphabets, is another open problem which was recently resolved for strings by Ellert and Fischer [3].
Acknowledgements
We thank Tomohiro I for pointing out the paper of [13], which enabled us to reduce the time complexity of our initial solutions.
This work was supported by JSPS KAKENHI Grant Numbers JP18K18002 (YN), JP17H01697 (SI), JP20H04141 (HB), JP18H04098 (MT), JST ACT-X Grant Number JPMJAX200K (YN), and JST PRESTO Grant Number JPMJPR1922 (SI).
The reference list from the paper itself. Each links out to its DOI / PubMed record.
- 1[1] R. M. Kolpakov, G. Kucherov, Finding maximal repetitions in a word in linear time , in: 40th Annual Symposium on Foundations of Computer Science, FOCS ’99, 17-18 October, 1999, New York, NY, USA, IEEE Computer Society, 1999, pp. 596–604. doi:10.1109/SFFCS.1999.814634 . URL https://doi.org/10.1109/SFFCS.1999.814634 · doi ↗
- 2[2] H. Bannai, T. I, S. Inenaga, Y. Nakashima, M. Takeda, K. Tsuruta, The “runs” theorem , SIAM J. Comput. 46 (5) (2017) 1501–1514. doi:10.1137/15M 1011032 . URL https://doi.org/10.1137/15M 1011032 · doi ↗
- 3[3] J. Ellert, J. Fischer, Linear time runs over general ordered alphabets , Co RR abs/2102.08670 (2021). ar Xiv:2102.08670 . URL https://arxiv.org/abs/2102.08670
- 4[4] R. Sugahara, Y. Nakashima, S. Inenaga, H. Bannai, M. Takeda, Computing Runs on a Trie , in: N. Pisanti, S. P. Pissis (Eds.), 30th Annual Symposium on Combinatorial Pattern Matching (CPM 2019), Vol. 128 of Leibniz International Proceedings in Informatics (LIP Ics), Schloss Dagstuhl–Leibniz-Zentrum fuer Informatik, Dagstuhl, Germany, 2019, pp. 23:1–23:11. doi:10.4230/LIP Ics.CPM.2019.23 . URL http://drops.dagstuhl.de/opus/volltexte/2019/10494 · doi ↗
- 5[5] T. Kociumaka, J. Pachocki, J. Radoszewski, W. Rytter, T. Walen, Efficient counting of square substrings in a tree, Theoretical Computer Science 544 (2014) 60–73.
- 6[6] M. Crochemore, C. S. Iliopoulos, T. Kociumaka, M. Kubica, J. Radoszewski, W. Rytter, W. Tyczynski, T. Walen, The maximum number of squares in a tree , in: J. Kärkkäinen, J. Stoye (Eds.), Combinatorial Pattern Matching - 23rd Annual Symposium, CPM 2012, Helsinki, Finland, July 3-5, 2012. Proceedings, Vol. 7354 of Lecture Notes in Computer Science, Springer, 2012, pp. 27–40. doi:10.1007/978-3-642-31265-6\_3 . URL https://doi.org/10.1007/978-3-642-31265-6_3 · doi ↗
- 7[7] T. Kociumaka, J. Radoszewski, W. Rytter, T. Walen, String powers in trees , Algorithmica 79 (3) (2017) 814–834. doi:10.1007/s 00453-016-0271-3 . URL https://doi.org/10.1007/s 00453-016-0271-3 · doi ↗
- 8[8] M. Funakoshi, Y. Nakashima, S. Inenaga, H. Bannai, M. Takeda, Computing maximal palindromes and distinct palindromes in a trie , in: J. Holub, J. Zdárek (Eds.), Prague Stringology Conference 2019, Prague, Czech Republic, August 26-28, 2019, Czech Technical University in Prague, Faculty of Information Technology, Department of Theoretical Computer Science, 2019, pp. 3–15. URL http://www.stringology.org/event/2019/p 02.html
