Abstract 1 Introduction 2 Results and technical overview 3 Proof of Theorem 2.10 References Appendix A A gap in the previous streaming algorithm for computing 𝒌-mismatch periods

Streaming Periodicity with Mismatches, Wildcards, and Edits

Taha El Ghazi ORCID DIENS, École normale supérieure de Paris, PSL Research University, France Tatiana Starikovskaya ORCID DIENS, École normale supérieure de Paris, PSL Research University, France
Abstract

In this work, we study the problem of detecting periodic trends in strings. While detecting exact periodicity has been studied extensively, real-world data is often noisy, where small deviations or mismatches occur between repetitions. This work focuses on a generalized approach to period detection that efficiently handles noise. Given a string S of length n, the task is to identify integers p such that the prefix and the suffix of S, each of length np+1, are similar under a given distance measure. Ergün et al. [APPROX-RANDOM 2017] were the first to study this problem in the streaming model under the Hamming distance. In this work, we combine, in a non-trivial way, the Hamming distance sketch of Clifford et al. [SODA 2019] and the structural description of the k-mismatch occurrences of a pattern in a text by Charalampopoulos et al. [FOCS 2020] to present a more efficient streaming algorithm for period detection under the Hamming distance. As a corollary, we derive a streaming algorithm for detecting periods of strings which may contain wildcards, a special symbol that match any character of the alphabet. Our algorithm is not only more efficient than that of Ergün et al. [TCS 2020], but it also operates without their assumption that the string must be free of wildcards in its final characters. Additionally, we introduce the first two-pass streaming algorithm for computing periods under the edit distance by leveraging and extending the Bhattacharya–Koucký’s grammar decomposition technique [STOC 2023].

Keywords and phrases:
approximate periods, pattern matching, streaming algorithms
Copyright and License:
[Uncaptioned image] © Taha El Ghazi and Tatiana Starikovskaya; licensed under Creative Commons License CC-BY 4.0
2012 ACM Subject Classification:
Theory of computation Pattern matching
Related Version:
Full Version: https://arxiv.org/abs/2509.14898
Funding:
Partially supported by the grant ANR-20-CE48-0001 from the French National Research Agency (ANR) and a Royal Society International Exchanges Award.
Editors:
Ho-Lin Chen, Wing-Kai Hon, and Meng-Tsung Tsai

1 Introduction

In this work, we consider the problem of computing periodic trends in strings. Informally, a string has period p if its prefix of length np+1 equals its suffix of length np+1. Alternatively, a string has period p if it equals its prefix of length p repeated a (possibly, fractional) number of times. The problem of detecting periodic trends in strings has numerous practical applications, including fields like astronomy, financial analytics, and meteorology (see e.g. [11]). The nature and the volume of the data in the applications ask for algorithms able to process the input in very little space and in (almost) real time, such as streaming algorithms. In the streaming setting, we assume that the input string arrives one character at a time and account for all space used, even for the space used to store information about the input data, which results in ultra-efficient algorithms.

The first streaming algorithm for detecting exact periods of a stream of length n was given by Ergün, Jowhari, and Sağlam [14], who presented an algorithm with O(log2n) space.111Hereafter, the space is measured in bits.

While the problem of detecting exact periodicity is fundamental to string processing, in practice data is rarely exactly periodic. For example, a string abcabcabaabaaba is clearly repetitive, but does not have a small exact period in the sense above. To account for these variations in natural data, Ergün, Jowhari, and Sağlam [14] proposed another streaming algorithm, which allows for approximately computing the Hamming distance (the number of mismatches) between a stream and a string with period p, for a given integer p. Their algorithm computes the distance with an approximation factor 2+ε in space O~(1/ε2). A disadvantage of this algorithm is that p must be known in advance, and knowing p approximately will not suffice.

Later, Ergün, Grigorescu, Azer, and Zhou [12] suggested a different version of this problem: given a string of length n and an integer k, they asked for all integer p such that the Hamming distance between the string and its copy shifted by p is at most k (see Section 2 for a definition). They called such p k-mismatch periods. They proved that for computing all k-mismatch periods of a streaming string of length n one needs Ω(n) space and that for computing all k-mismatch periods in [1..n/2], one needs Ω(klogn) space. On the other hand, prior work [12, 15] claimed a streaming algorithm that, given a string of length n, computes all its k-mismatch periods in [1..n/2] using only O(k4log9n) space. However, we found significant gaps in the proof of correctness. Many key arguments are only briefly outlined in both the conference version [12] and the longer arXiv manuscript [15], and as confirmed in private communication with the authors, a full journal version of the paper has not been published. In particular, [15, Theorem 28] is proved only for the case when the string has two distinct k-mismatch periods, and is stated to generalize easily to the case when the string has more than two distinct periods. We believe this generalization does not hold; see Appendix A for a detailed explanation.

Finally, in a different work [13] Ergün, Grigorescu, Azer, and Zhou considered the problem of computing periods of incomplete streaming data, where some characters are replaced with wildcards, a special symbol that matches each character of the alphabet. We say that a wildcard-containing string T has an integer period p if T shifted by p positions matches itself. They showed that a streaming algorithm which computes all periods of an n-length string with wildcards requires Ω(n) space. Conversely, they demonstrated a streaming algorithm which given a string T with k wildcards computes all its periods pn/2 under condition that there are no wildcards in the last p characters of T. The algorithm uses O(k3polylogn) space. They also showed that for k=o(n), such an algorithm must use Ω(klogn) space.

Our results

In this work, we continue the study initiated by Ergün, Grigorescu, Azer, and Zhou [12]. We first give a streaming algorithm for computing the k-mismatch periods of a string (Theorem 2.10), providing full details and improving over the claimed space bound of Ergün, Grigorescu, Azer, and Zhou [12] by a factor of k2log5n.

As an almost immediate corollary, and our second contribution, we obtain a similar result for computing periods of a string with few wildcards (Theorem 2.2). Specifically, we both improve the complexity of the algorithm by Ergün, Grigorescu, Azer, and Zhou [13] by a factor of kpolylogn, narrowing the gap between the upper and lower bounds, and remove the assumption that there are no wildcards in the last characters of the input string.

As our third and final contribution, we extend our results to the edit distance. Informally, we say that a string has a k-edit period pn/2 if the edit distance (the number of deletions, insertions, and substitutions required to transform one string into another) between the input string and its copy shifted by p characters is at most k (see Section 2 for a formal definition). We apply the Bhattacharya–Koucký’s grammar decomposition [4] and then show that we can compute the k-edit periods of the input by computing the k-mismatch periods of the stream of suitably encoded grammars. As our algorithm for k-mismatch periods needs to know the length of the stream (assumption already present in [12]), we make two passes: first, we compute the decomposition and the length of the stream, and in the second pass we compute the periods. As a result, we develop the first two-pass streaming algorithm for computing k-edit periods of a string in O~(k2n) time and O~(k4) space (Theorem 2.3).222Hereafter, O~ means that we hide factors polylogarithmic in n. “Two-pass” means that the algorithm reads T as a stream twice. We emphasize that in this work, we deliberately chose to treat our algorithm for k-mismatch periods as a black box, using it as a direct application in the context of k-edit periods. While it is conceivable that opening this black box and combining its internal components with the Bhattacharya–Koucký technique could lead to a one-pass streaming algorithm for k-edit periods, pursuing this direction would require significant new insights. We leave this as a promising open question for future research.

Related work

Other repetitive string structures that have been considered in the literature include palindromes (strings that read the same forward and backwards) and squares (strings equal to two copies of a string concatenated together). Berebrink et al. [3] followed by Gawrychowski et al. [16] studied the question of computing the length of a maximal palindromic substring of a stream that is a palindrome. Merkurev and Shur [21] considered a similar question for squares. Bathie et al. [1] considered the problem of recognising prefixes of a streaming string that are at Hamming (edit) distance at most k from palindromes and squares.

2 Results and technical overview

In this work, we assume the word-RAM model of computation and work in a particularly restrictive streaming setting. In this setting, we assume that the input string arrives as a stream, one character at a time. We must account for all the space used, including the space used to store information about the input. Throughout, the space is measured in bits.

Notations and terminology

We assume to be given an alphabet Σ, the elements of which, called characters, can be stored in a single machine word of the word-RAM model. For an integer n0, we denote the set of all length-n strings by Σn, and we set Σn=m=0nΣm as well as Σ=n=0Σn. The empty string is denoted by ε. For two strings S,TΣ, we use ST or ST indifferently to denote their concatenation. For an integer m0, the string obtained by concatenating S to itself m times is denoted by Sm; note that S0=ε. Furthermore, S denotes an infinite string obtained by concatenating infinitely many copies of S. For a string TΣn and i[1..n],333For integers i,j, denote [i..j]={k:ikj}, [i..j)={k:ik<j}, and (i..j]={k:i<kj}. the ith character of T is denoted by T[i]. We use |T|=n to denote the length of T. For 1i,jn, T[i..j] denotes the substring T[i]T[i+1]T[j] of T if ij and the empty string otherwise. When i=1 or j=n, we omit them, i.e., we write T[..j]=T[1..j] and T[i..]=T[i..n]. We say that a string P is a prefix of T if there exists j[1..n] such that P=T[..j], and a suffix of T if there exists i[1..n] such that P=T[i..]. A non-empty string TΣn is primitive if T2[i..j]=T implies i=1 or i=|T|+1.

2.1 𝒌-mismatch periods

The Hamming distance between two strings S,T (denoted 𝗁𝖽(S,T)) is defined to be equal to infinity if S and T have different lengths, and otherwise to the number of positions where the two strings differ (mismatches). We define the mismatch information between two length-n strings S and T, 𝖬𝖨(S,T) as the set {(i,S[i],T[i]):i[1..n] and S[i]T[i]}. An integer p is called a k-mismatch period of a string T of length n if 1pn and 𝗁𝖽(T[1..np+1],T[p..n])k.

Theorem 2.1 (Informal statement of Theorem 2.10).

Given a string T of length n and an integer k, there is a streaming algorithm that computes all k-mismatch periods of T in [1..n/2]. Furthermore, for each detected k-mismatch period p, it also returns 𝖬𝖨(T[p..],T[..np+1]). The algorithm uses O(nklog5n) time and O(k2log3n) space, and is correct w.h.p.444Hereafter, w.h.p. stands for probability at least 11/nc, for a constant c>1.

To develop our result, we start with a simple idea already present in [12]: If p is a k-mismatch period of T, then for all 1np, the position p is a starting position of a k-mismatch occurrence of T[1..+1]. This already allows to filter out candidate periods. To test whether an integer p is a k-mismatch period, we check if the Hamming distance between T[1..np+1] and T[p..n] is at most k. For this, we aim to use the Hamming distance sketches introduced by Clifford, Kociumaka, and Porat [9] for strings T[1..np+1] and T[p..n]. There are two main challenges: First, we might discover a candidate k-mismatch period p after passing position np+1, which would make it impossible to compute the Hamming distance sketch of T[1..np+1] due to streaming access limitations. To address this, as in [12], we divide the interval [1..n/2] into a logarithmic number of subintervals, filtering positions in each subinterval using progressively shorter prefixes. The second challenge is that the number of candidate periods can be large, and we cannot store all the sketches. Here, we diverge significantly from [12]: To store the sketches in small space, we leverage the concatenability of the Hamming distance sketches of [9] and the structural regularity of k-mismatch occurrences as shown by Charalampopoulos, Kociumaka, and Wellnitz [8]. Combining the two ideas together is non-trivial and this is where the main novelty of our result for the Hamming distance is. The proof of Theorem 2.10 is given in Section 3.

Assume to be given a string containing wildcards. By replacing wildcards in a string with a new character, we immediately derive the following:

Theorem 2.2.

Given a string T of length n containing at most k wildcards. There is a streaming algorithm that computes the set of periods of T in [1..n/2] in O(nklog5n) time and O(k2log3n) space. The algorithm is correct w.h.p.

Proof.

If we replace the wildcards in T with a new character #Σ, then a period p of T is a k-mismatch period of the resulting string in the alphabet Σ{#}, and we can find it via Theorem 2.1. To check that the positions returned by the algorithm are periods of the original string, for each detected k-mismatch period, we retrieve the relevant mismatch information and verify that for all mismatching pairs of characters, at least one of those is the special character #.

2.2 𝒌-edit periods

The edit distance between two strings S,T (denoted by 𝖾𝖽(S,T)) is the minimum number of character insertions, deletions, and substitutions required to transform S into T. We say that an integer p is a k-edit period of a string T of length n if 1p|T| and for some 1in, 𝖾𝖽(T[1..i],T[p..n])k.

Theorem 2.3.

Given a string T of length n and an integer k, there is a two-pass streaming algorithm that computes all k-edit periods of T in O~(k2n) time and O~(k4) space. The algorithm is correct w.h.p.

2.2.1 Preliminaries: Grammar decomposition

We assume familiarity with the notion of straight-line programs (SLP) [18], which represent a subclass of context-free grammars. The size of an SLP G is the number of non-terminals and is denoted by |G|. Furthermore, G represents a unique string, called the expansion of G, 𝖾𝗑𝗉(G). The length of |𝖾𝗑𝗉(G)| can be computed in O(|G|) time and space [20].

Fact 2.4.

Let GX and GY be SLPs representing strings X and Y respectively, and m=|GX|+|GY|. Both of the following hold:

  • We can compute d:=𝖾𝖽(X,Y) in O((m+d2)log|XY|) time and O(mlog|XY|) space (see [5, Proposition 2.1]).

  • Given an integer k, we can find all 1i|Y| such that 𝖾𝖽(X,Y[i..])k and the corresponding edit distances in O((m+k2)log|XY|) time and O(mlog|XY|) space.

Proof.

By [19] (see also the remark at the end of [10, Section 5]), all such positions i can be found in (k+1)2 longest common extension (LCE) queries on a string Z equal to the reverse of XY. Given two positions 1i,j|Z|, an LCE query asks for the maximal such that Z[i..i+1]=Z[j..j+1]. The string Z can be represented as the expansion of an SLP of size O(|GX|+|GY|). I [17] showed that after O(mlog|Z|)-time and -space preprocessing of the SLP555The result of I [17] gives tighter bounds, but this is sufficient for our purposes, LCE queries on Z can be answered in O(log|Z|) time. The claim follows. One of the central tools of our solution is Bhattacharya–Koucký’s grammar decomposition (BK-decomposition) [4]. It is a randomised decomposition that uses as source of randomness two families of hash functions C1,,CL and H0,,HL, where L=O(logn) is a suitably chosen parameter. The decomposition of a string X is a sequence 𝒢(X) of SLPs.666Strictly speaking, the decomposition [4] outputs run-length SLPs. However, one can transform those grammars into SLPs with a size blow-up polylogarithmic in n [20]. For a sequence of SLPs 𝒢=G1Gm, define 𝖾𝗑𝗉(𝒢)=𝖾𝗑𝗉(G1)𝖾𝗑𝗉(Gm).

Fact 2.5 ([4, Theorem 3.1]).

Let XΣn, k be the input parameter of the grammar decomposition algorithm, and let 𝒢(X)=G1XGsX. For all n large enough, X=𝖾𝗑𝗉(𝒢(X)) and |GiX|=O~(k) for i{1,,s} with probability 12/n.

The BK-decomposition can be maintained in a streaming fashion:

Corollary 2.6 ([6, Lemma 4.2,Theorem 5.1]).

Given a streaming string XΣ, there is an algorithm that outputs a stream of SLPs 𝒢def=G1Gs (referred to as definite) and maintains a sequence 𝒢active=G1Gt of O~(1) SLPs (referred to as active) such that after having read X[1..i], the concatenation of 𝒢def and 𝒢active equals 𝒢(X[1..i]). The algorithm uses O~(k) time per character and O~(k) space (here, we account for all the space used except for the space required to store 𝒢def). The only operation the algorithm is allowed to perform on 𝒢def is appending a grammar from the right.

We further make use of the following claim:

Corollary 2.7.

Let kn be integers. Assume X,Y,U,VΣ, |XU|,|VY|n, and 𝖾𝖽(X,Y)k. Let 𝒢(XU)=G1Gs and 𝒢(VY)=G1Gs. With probability at least 11/5, there exist integers r,r,t,t such that each of the following is satisfied (see Figure 1):

  1. 1.

    t+1=st+1.

  2. 2.

    X=𝖾𝗑𝗉(G1Gt)𝖾𝗑𝗉(Gt+1)[..r] and Y=𝖾𝗑𝗉(Gt)[r..]𝖾𝗑𝗉(Gt+1Gs).

  3. 3.

    Gi=Gt+i1 except for at most k+2 indices 1it+1.

  4. 4.

    𝖾𝖽(X,Y) equals the sum of 𝖾𝖽(𝖾𝗑𝗉(G1),𝖾𝗑𝗉(Gt)[r..]), 2it𝖾𝖽(𝖾𝗑𝗉(Gi),𝖾𝗑𝗉(Gt+i1)), and 𝖾𝖽(𝖾𝗑𝗉(Gt+1)[..r],𝖾𝗑𝗉(Gs)).

Bhattacharya and Koucký [4] proved a similar result in the case where V and V are appended to X and Y, respectively, from the left. By construction, the BK-decomposition is (almost) symmetric, which allows to adapt their argument to show an analogous result for the case where U and U are appended to X and Y, respectively, from the right. Corollary 2.7 follows by first applying the result of Bhattacharya and Koucký [4] with V=ε, and then using our analogous argument with U=ε.

Figure 1: Grammar decompositions for VY and XU for the case 𝖾𝖽(X,Y)k.

Finally, we use the following encoding of SLPs that allows reusing algorithms on strings for sequences of SLPs:

Fact 2.8 ([4, Lemma 3.13]).

Let μ=O~(k) be a parameter. There is a mapping enc from the set of SLPs output by the BK-decomposition algorithm to the set of strings of length μ on an alphabet Γ of size polynomial in n (the maximum length of the input string of the BK-decomposition algorithm) that guarantees that the following is satisfied:

  1. 1.

    A grammar can be encoded and decoded in O(μ) time and space;

  2. 2.

    Encodings of two equal grammars are equal;

  3. 3.

    Encodings of two distinct grammars output by the decomposition algorithm differ in all μ characters with probability at least 11/n.

2.2.2 Proof of Theorem 2.3

A high-level idea of our algorithm is to apply the grammar decomposition to the stream, and then to reduce the problem to the problem of computing periods with mismatches via Corollary 2.7 and ˜2.8. To this end, we need a stronger version of a streaming algorithm for computing periods with mismatches, and in particular, we introduce a weight function w on strings. In the case of the Hamming distance, this function is identically zero. In case of the edit distance, we define it as a partial function on Γ, namely, if ΓS=enc(G1Gm), then w(S)=|𝖾𝗑𝗉(G1Gm)|.

Proposition 2.9.

The weight functions defined above satisfy each of the following:

  • For a string S of length n, w(S) can be computed in streaming deterministically using tw(n) time per character and sw(n) space;

  • Consider strings X,Y. If at least two of w(X),w(Y),w(XY) are defined, then the third one is defined as well and w(XY)=w(X)+w(Y);

  • Consider strings X,Y that have equal length in [1..n]. If w(X),w(Y) are defined, then w(Y) can be computed deterministically in |𝖬𝖨(X,Y)|tw(n) time and sw(n) space.

For the Hamming distance, tw(n)=O(1) and sw(n)=O(1) (trivially), and for the edit distance tw(n)=O~(1) and sw(n)=O~(k).

Proof.

The claim is trivial for w0. In the following, we consider the weight function for the edit distance. First, consider S=enc(G1G2Gm). Its weight w(S) can be computed in streaming using tw(n) time per character, where tw(n)=O~(1) and sw(n)=O~(k) space thanks to ˜2.8. The second property obviously holds. Finally, assume X=enc(G1G2Gm) and Y=enc(G1G2Gm). Let ={im,enc(Gi)enc(Gi)}. Given 𝖬𝖨(X,Y), because of ˜2.8, we have access to all characters in enc(Gi) and enc(Gi) for i. As a result, we can compute w(Y)=w(X)+iw(enc(Gi))w(enc(Gi)) in 𝖬𝖨(X,Y)tw(n) time and sw(n) space.

In Section 3, we show the following theorem:

Theorem 2.10.

Given a string T of length n and integers k,Δ, there is a streaming algorithm that computes all k-mismatch periods of T in [1..n/2+Δ]. Furthermore, for each detected k-mismatch period p, it also returns weight w(T[p..]) and 𝖬𝖨(T[p..],T[..np+1]). The algorithm runs in O(nktw(n)log5n) time, uses O(k2log3n+sw(n)+Δ(klogn+sw(n))) space, and is correct w.h.p., where tw(n) and sw(n) are as defined in Proposition 2.9.777By taking w0 and Δ=0, we immediately obtain Theorem 2.1.

Let us now explain how it implies the algorithm for computing k-edit periods. Recall that we receive a string T of length n as a stream. In the first streaming pass on T, we apply Corollary 2.6. At every moment of the algorithm, we additionally store the number of definite grammars. By Corollary 2.6, we can then compute m:=|𝒢(T)| in O~(kn) time and O~(k) space.

In the second streaming pass, we again run the algorithm of Corollary 2.6. When a new character arrives, we update the SLPs and if a SLP G becomes definite, i.e. if we append G to the stream of definite grammars, we compute enc(G) in O~(k) time and space (˜2.8), and feed it character-by-character into the μ(k+2)-mismatch period algorithm (Theorem 2.10), where μ is the parameter from ˜2.8. Consider the moment when we arrive at the end of T and let G1,,Gt be the active grammars. We compute enc(G1Gt) and feed it by character-by-character into the μ(k+2)-mismatch period algorithm. Let 𝒯 be the resulting stream we fed into the algorithm, i.e. 𝒯=enc(𝒢(T)), where 𝒢(T)=G1TG2TGmT.

The μ(k+2)-mismatch period algorithm retrieves all μ(k+2)-mismatch periods of 𝒯 one-by-one. When a μ(k+2)-mismatch period p is retrieved, we do the following. If p1 is not a multiple of μ, we discard it immediately. Otherwise, by Corollary 2.7, there are at most k+2 values 2im(p1)/μ1 such that enc(GiT)enc(Gi+(p1)/μT). We retrieve the set I containing all such i from 𝖬𝖨(𝒯[p..],𝒯[..mμp+1]). We finally compute

d(p)=iI𝖾𝖽(𝖾𝗑𝗉(GiT),𝖾𝗑𝗉(Gi+(p1)/μT))+minr𝖾𝖽(𝖾𝗑𝗉(Gm(p1)/μT)[..r],𝖾𝗑𝗉(GmT))

If d(p)k, we compute all r such that 𝖾𝖽(𝖾𝗑𝗉(G1T),𝖾𝗑𝗉(G1+(p1)/μT[r..]))kd(p). For all such r, we return w(enc(G(p1)/μ+2TGmT))+r as a k-edit period of T.

Correctness.

If pn/2 is a k-edit period of T, there exists i such that 𝖾𝖽(T[..i],T[p..])k. By Corollary 2.7, there exist integers r,r,t,t such that T[..i]=𝖾𝗑𝗉(G1TGtT)𝖾𝗑𝗉(Gt+1T)[..r], T[p..]=𝖾𝗑𝗉(Gt)[r..]𝖾𝗑𝗉(Gt+1TGmT), t+1=mt+1 and there are at most k+2 indices i such that GiT and Gt+iT mismatch. By ˜2.8, tμ+1 is a μ(k+2)-mismatch period of 𝒯. Further, t(m+k)/2+1:

Claim 2.11.

t(m+k)/2+1.

Proof.

We have i(np+1)k and hence i+(np+1)nk. Consequently, t+1+(mt+1)mk. Indeed, assume towards a contradiction that t+(mt+1)mk. We then have

i+(np+1)
|𝖾𝗑𝗉(G1TGtT)𝖾𝗑𝗉(Gt+1T)[..r]|+|𝖾𝗑𝗉(Gt)[r..]𝖾𝗑𝗉(Gt+1Gm)|
|𝖾𝗑𝗉(G1TGt+1T)|+|𝖾𝗑𝗉(GtTGmT)||𝖾𝗑𝗉(G1TGt+1T)|+|𝖾𝗑𝗉(Gt+k+2TGmT)|
nk

where the last inequality holds as each SLP GiT, t+1<i<t+k+2 is non-trivial and hence its expansion has length at least one. Finally, since t+1=mt+1, we obtain mt+1(mk)/2 and therefore t(m+k)/2+1.

Consequently, tμ+1 is detected by the μ(k+2)-mismatch period algorithm with Δ=μ(k/2+1)+1. We then identify p as a k-edit period of T by computing the edit distances between the expansions of the mismatching SLPs.

The algorithm fails if Corollary 2.7 fails, or if the μ(k+2)-mismatch period algorithm fails, or if ˜2.8 fails, which happens with probability 25 for n big enough. Also, notice that when Corollary 2.7 fails, the algorithm computes edit distance that is bigger than the actual distance. As a result, with a standard argument, we can run logn instances of the algorithm and return the minimal computed distance, to have the algorithm succeed w.h.p.

Complexity.

The first pass on T takes O~(kn) time and O~(k) space. For the second pass, the μ(k+2)-mismatch period algorithm takes O~(μktw(n)n)=O~(k2n) time and O~((μk)2+sw(n))=O~(k4) space by Theorem 2.10 and Proposition 2.9. For each μ(k+2)-mismatch period returned by the algorithm, we can bound the time needed to compute d(p) as follows: Let ki=𝖾𝖽(𝖾𝗑𝗉(Gi),𝖾𝗑𝗉(Gi+(p1)/μ)). By ˜2.4, we can compute ki in time O~(ki2), hence if d(p)k, we can compute d(p) in time O~(iki2)=O~(k2). If the edit distance computations take total time more than O~(k2), we can terminate them as we know that d(p)>k.888To be more precise, we upper bound the number of longest common extension queries from 2.4, it should not exceed i(ki+1)2(k+1)2. Theorem 2.3 follows.

3 Proof of Theorem 2.10

In this section, we prove Theorem 2.10. We first recall essential tools for the Hamming distance, then outline our algorithm and solve each case, and finally analyse it.

3.1 Tools for the Hamming distance

For two strings P,T, a position i[|P|..|T|] of T is a k-mismatch occurrence of P in T if 𝗁𝖽(T[i|P|+1..i],P)k. For an integer k, we define 𝗁𝖽k(X,Y)=𝗁𝖽(X,Y) if 𝗁𝖽(X,Y)k and otherwise. We denote by OcckH(P,T) the set of k-mismatch occurrences of P in T. For brevity, we define 𝗁𝖽(P,T)=𝗁𝖽(P,T[1..|P|]).

Fact 3.1 ([9, Lemmas 6.2-6.4]).

Consider positive integers k,n,σ such that kn and σ=nO(1), and a family 𝒰{0,,σ1}n of strings. One can assign O(klogn)-bit sketches 𝗌𝗄k(U) to all strings U𝒰 so that each of the following holds, assuming that all processed strings belong to 𝒰:

  1. 1.

    Given sketches 𝗌𝗄k(U),𝗌𝗄k(V), there is an algorithm that uses O(klog3n) time to decide whether 𝗁𝖽(U,V)k. If so, 𝖬𝖨(U,V) is reported.

  2. 2.

    There is an algorithm that constructs one of 𝗌𝗄k(U),𝗌𝗄k(V) or 𝗌𝗄k(UV) given the two other sketches in O(klogn) time.

  3. 3.

    There is an algorithm that constructs 𝗌𝗄k(U) or 𝗌𝗄k(Um) given the other sketch and the integer m in O(klogn) time.

  4. 4.

    If 𝗁𝖽(U,V)=O(k), there is an algorithm that constructs 𝗌𝗄k(V) from 𝗌𝗄k(U) and 𝖬𝖨(U,V) in O(klog2n) time.

All algorithms use O(klogn) space and succeed w.h.p.

Below, we refer to the sketch of ˜3.1 as the k-mismatch sketch. Note that for a string U and all integer kk, the sketch 𝗌𝗄k(U) includes the sketch 𝗌𝗄k(U) (see [9] for a definition). Beyond the properties above, the k-mismatch sketch has one additional property:

Corollary 3.2 ([9, Fact 4.4]).

There exists a streaming algorithm that processes a string U in O(klogn) space using O(log2n) time per character so that the sketch 𝗌𝗄k(U) can be retrieved on demand in O(klog2n) time.

By analysing the details of [9, Corollary 3.4], one can derive a streaming algorithm for computing all occurrences of a pattern in a text when the pattern is a prefix of some string and the text is a substring of the same string, which we refer to as the k-mismatch algorithm:

Corollary 3.3.

Given a string T of length n, there is a streaming algorithm for a pattern P=T[1..] and a text T[i..j], where 1i,j,n, which uses O(klog2n) space and takes O(klog4n) time per arriving character. The algorithm reports all positions p such that i+1pj and 𝗁𝖽(T[p+1..p],P)k at the moment of their arrival. For each reported position p, 𝖬𝖨(T[p+1..p],P) and 𝗌𝗄k(T[1..p]) can be reported on demand in O(klog2n) time at the moment when p arrives. The algorithm is correct w.h.p.

Proof.

Clifford et al. [9, Corollary 3.4] presented an algorithm that reports the endpoints of all k-mismatch occurrences of a pattern in a text assuming that it first receives the pattern as a stream and then a text as a stream as well. The algorithm uses O(klog2n) space and takes O(klog4n) time per arriving character and is correct w.h.p.

This is not the current best algorithm (presented in Clifford et al. [9] as well). The reason why we selected the simpler algorithm is that it allows for the necessary preprocessing of the pattern to be easily done before one needs it for the text processing. Namely, the only information the algorithm stores about the pattern are the k-mismatch sketches of the prefixes of the pattern of the lengths equal to powers of two, and the k-mismatch sketch of the pattern itself, computed via Corollary 3.2, and the k-mismatch sketch of the pattern’s prefix of length is never used before the position +1 of the text.

Fact 3.4 (cf. [8, Theorems 3.1 and 3.2]).

Given a pattern P of length m, a text T of length n32m, and a threshold k{1,,m}, at least one of the following holds:

  1. 1.

    The number of k-mismatch occurrences of P in T is bounded by 576n/mk.

  2. 2.

    There is a primitive string Q of length |Q|m/128k that satisfies 𝗁𝖽(P,Q)2k.

In the second case, the difference between the starting positions of any two k-mismatch occurrences of P in T is a multiple of |Q| and if T is the minimal substring of the text containing all k-mismatch occurrences of P in T, then 𝗁𝖽(T,Q)6k.

Let S be a string of length n. For our next lemma, we introduce the forward cyclic rotation 𝗋𝗈𝗍(S)=S[n]S[1]S[n1]. In general, for s, a cyclic rotation 𝗋𝗈𝗍s(S) with shift s (resp. s) is obtained by iterating 𝗋𝗈𝗍 (resp. 𝗋𝗈𝗍1) s times. Note that a string S is primitive if and only if 𝗋𝗈𝗍s(S)=S implies s=0(mod|S|).

Lemma 3.5.

Given two strings X,Y such that X is a prefix of Y and |Y|52|X|. Assume that there are primitive strings QX such that 𝗁𝖽(QX,X)k and |QX||X|128k and QY such that 𝗁𝖽(QY,Y)k and |QY||Y|128k. We then have QX=QY.

Proof.

Suppose towards a contradiction that QXQY. By the triangle inequality, we have 𝗁𝖽(QX[1..|X|],QY[1..|X|])2k and max{|QX|,|QY|}|Y|128k5|Y|256. Assume w.l.o.g. |QX||QY|.

If there is i such that |QY|=i|QX|, then by primitivity of QY, we have 𝗁𝖽(QY,QXi)1, and 𝗁𝖽(QY[1..|X|],QX[1..|X|])|X||QY|128k|X||Y|2565k>2k. Otherwise, for all 1j|QX| we have

𝗁𝖽(QY2,𝗋𝗈𝗍j(QX))==𝗁𝖽(QY,𝗋𝗈𝗍j(QX)[1..|QY|])+𝗁𝖽(QY,𝗋𝗈𝗍j(QX)[|QY|+1. .2|QY|])==𝗁𝖽(QY,𝗋𝗈𝗍j(QX)[1..|QY|))+𝗁𝖽(QY,𝗋𝗈𝗍j+|QY|(QX)[1..|QY|])1

The last inequality holds because jj+|QY|(mod|QX|) and QX is primitive. Hence, 𝗁𝖽(QY[1..|X|],QX[1..|X|])|X|2|QY|1285k>2k, and QY=QX.

3.2 Structure of the algorithm

We can test a position in the following way to decide whether it is a k-mismatch period:

Proposition 3.6.

Given 𝗌𝗄k(T), 𝗌𝗄k(T[1..p1]) and 𝗌𝗄k(T[1..np+1]) for an integer 1pn, there is an algorithm that can decide whether p is a k-mismatch period of T using O(klog3n) time and O(klogn) space. In this case, it also returns 𝖬𝖨(T[p..],T[..np+1]). The algorithm is correct w.h.p.

Proof.

First, the algorithm applies ˜3.1 to compute 𝗌𝗄k(T[p..]) from 𝗌𝗄k(T) and 𝗌𝗄k(T[1..p1]) in O(klogn) time and space. By ˜3.7, p is a k-mismatch period of T iff h=𝗁𝖽(T[1..np+1],T[p..n])k. Given 𝗌𝗄k(T[p..]) and 𝗌𝗄k(T[1..np+1]), ˜3.1 allows to decide whether hk in O(klog3n) time and O(klogn) space.

For p[n/2+1..n/2+Δ], our algorithm computes the sketches required by Proposition 3.6 via ˜3.1 and the weights w(T[p..]) via Proposition 2.9 using O(nklogn+Δtw(n)) total time and O(Δ(klogn+sw(n))) space. After reaching the end of T, the algorithm tests each of the candidates p[n/2+1..n/2+Δ] in O(Δklog3n)=O(nklog3n) total time and O(klogn) space, and for each k-mismatch period, returns p, w(T[p..]), and 𝖬𝖨(T[p..],T[..np+1]).

The rest of the section is devoted to computing periods p[1..n/2]. The following simple observation is crucial for the correctness of our algorithm.

Observation 3.7.

An integer 1pn is a k-mismatch period of T iff 𝗁𝖽(T[1..np+1],T[p..n])k. As a corollary, if p is a k-mismatch period of T, then for all 1np, the position p is the starting position of a k-mismatch occurrence of T[1..+1].

It follows that we can use k-mismatch occurrences of appropriately chosen prefixes of T in T to filter out candidate k-mismatch periods. For j=1,,log3/2n, define j:=n/(3/2)j, Pj=T[1..j], and Tj=T[max{n/2j,1}..n/2j+1+j2]. For each j, we give two algorithms run in parallel, which together compute the set 𝒫kj of all k-mismatch periods of T in the interval [n/2j..n/2j+11]. The first algorithm assumes that the number of k-mismatch occurrences of Pj in Tj is at most K=576k (we call such Pj “non-periodic”, slightly abusing the standard definition), while the second one is correct when the number of occurrences is larger than K (we call such Pj “periodic”).

3.3 The algorithm for non-periodic 𝑷𝒋

We maintain the sketch and the weight of the current text T using Corollary 3.2 and Proposition 2.9 in O(log2n+tw(n)) time per character and O(klogn+sw(n)) space. After reading Pj=T[1..j], we memorise w(Pj). Additionally, we run the k-mismatch algorithm (Corollary 3.3) for a pattern Pj and a text Tj, which in particular computes 𝗌𝗄k(Pj). Furthermore, we maintain two hash tables, each of size at most K, Prefj and Sufj. Intuitively, we want Prefj to contain every position p which is the starting position of a k-mismatch occurrence of Pj in Tj, associated with 𝗌𝗄k(T[1..p1]) and the weight of T[1..p1]. As for the table Sufj, we would like it to contain every position t such that nt+1Prefj, again associated with 𝗌𝗄k(T[1..t]) and the weight of T[1..t]. We implement Prefj and Sufj via the cuckoo hashing scheme [22] and de-amortise as explained in [2, Theorem A.1] to yield the following:

Fact 3.8 ([22, 2]).

A set of K integers in {0,1}w, where w=Θ(logn) is the size of the machine word, can be stored in O(Klogn) space while maintaining look-up queries in O(1) worst-case time and insertions in O(1) worst-case time w.h.p.

When we receive a character T[p], the tables are updated as follows. Assume first that the k-mismatch algorithm detects a new occurrence of Pj ending at the position p. We retrieve 𝗌𝗄k(T[1..pj]) and 𝖬𝖨(Pj,T[pj+1..p]) in O(klog2n) time (˜3.1). Furthermore, with w(Pj), we can deduce w(T[pj+1..p]), and finally, with w(T[..p]), we compute w(T[1..pj]), and add pj associated with 𝗌𝗄k(T[1..pj]) and w(T[1..pj]) to Prefj in O(ktw(n)) time and O(sw(n)) space. Secondly, if for t=np we have tPrefj, we add p associated with 𝗌𝗄k(T[1..p]) to Sufj. If either of the two insertions takes more than constant time or if the size of any of Prefj and Sufj becomes larger than K, the algorithm terminates and returns . Assume that the algorithm has reached the end of T.

Proposition 3.9.

If t𝒫kj, then t1Prefj and nt+1Sufj.

Proof.

As t𝒫kj, by ˜3.7 t+j1 is the ending position of a k-mismatch occurrence of Pj in T. Furthermore, t[n/2j..n/2j+11], and hence T[t,t+j1] is a fragment of Tj. This proves that t1Prefj. To show that nt+1Sufj, note that

2t2(n/2j+11)n2j+12nj.

Therefore, t+j1<nt+1, and t1 will be added to Prefj before nt+1. The claim follows.

Finally, the algorithm considers each position tPrefj, extracts 𝗌𝗄k(T[1..t]) from Prefj and 𝗌𝗄k(T[1..nt]) from Sufj and if t passes the test of Proposition 3.6, reports t+1 as a k-mismatch period of T, and returns w(T[t+1..])=w(T)w(T[1..t]).

Proposition 3.10.

Assume that the number of occurrences of Pj in Tj is at most K=576k. The algorithm computes 𝒫kj and 𝖬𝖨(T[p..],T[..np+1]),p𝒫kj in O(n(klog4n+tw(n))) time and O(k2log2n+sw(n)) space and is correct w.h.p.

Proof.

The algorithm runs an instance of the k-mismatch algorithm (Corollary 3.3) that takes O(nklog4n) time and O(klog2n) space. Computing weights takes O(ntw(n)) time and sw(n) space. Adding elements to Prefj and Sufj, as well as look-ups, takes O(1) time per element, and we add at most K=O(k) elements in total. The two hash tables occupy O(k2log2n) space (˜3.8, ˜3.1). Finally, testing all candidate positions requires O(Kklog3n)=O(nklog3n) time and O(klogn) space (Proposition 3.6). The correctness of the algorithm follows from Proposition 3.9 and Proposition 3.6. The algorithm can fail if the k-mismatch algorithm errs, or if adding an element to the hash tables takes more than constant time, or if the test fails. By the union bound, Corollary 3.3, ˜3.1, and Proposition 3.6, the failure probability is inverse-polynomial in n.

3.4 The algorithm for periodic 𝑷𝒋

We first explain how we preprocess Pj. Recall the Boyer–Moore majority vote algorithm:

Fact 3.11 ([7]).

Given a sequence e1,,em of elements, there is a streaming algorithm that stores O(1) elements of the sequence and returns a majority element if there exists one (otherwise, it can return an arbitrary element). Assuming constant-time access and comparison on the elements, the algorithm takes O(m) time.

Lemma 3.12.

Given a prefix P=T[1..] of T, there is a streaming algorithm that uses O(k(sw(n)+log2n)) space and runs in O(klog4n+tw(n)+k2log2n) time. If there is a primitive string Q of length |Q|128k that satisfies 𝗁𝖽(P,Q)<2k, the algorithm computes, correctly w.h.p., |Q|, 𝗌𝗄3k(Q), and w(Q) before or upon the arrival of T[(/|Q|2)|Q|]. If there is no such string, the algorithm determines it before T[] arrives.

Proof.

The main idea of the lemma is that |Q| must be the starting position of the first Θ(k)-mismatch occurrence of P[1..2] in T[2..]. As soon as we know |Q|, we compute the 3k-mismatch sketches and the weights of Θ(k) consecutive substrings of length |Q|. By ˜3.4, the majority of them equal Q, which allows computing 𝗌𝗄3k(Q) and w(Q) via the Boyer–Moore majority vote algorithm [7]. We now provide full details.

For brevity, let =2. We run the 8k-mismatch algorithm for a pattern P[1..] and a text T[2..]. If the 8k-mismatch algorithm does not detect an occurrence of P before or when reading the position +128k<, the algorithm concludes that Q does not exist and terminates. Assume now that the algorithm does detect a 8k-mismatch occurrence of the pattern ending at a position p, p+128k, and let it be the first detected occurrence. The instance of the 8k-mismatch algorithm is immediately terminated and we launch the majority vote algorithm (˜3.11). Let q=p+1 and p the smallest multiple of q greater than p. We then compute 𝗌𝗄3k(T[p+1..p+q]), 𝗌𝗄3k(T[p+q+1..p+2q]), …, 𝗌𝗄3k(T[p+(12k1)q+1..p+12kq]) via Corollary 3.2 and feed them into the majority vote algorithm. After all the 12k sketches have been computed, which happens when we read the position p+12kq(/q2)q, we return q and the output of the majority vote algorithm as 𝗌𝗄3k(Q). Using the same majority vote approach, we compute w(Q).

We now show the correctness of the algorithm. We start by showing that if Q exists, then q=|Q|. Let i be a multiple of |Q| smaller than /2. By ˜3.4 and the triangle inequality, we have 𝗁𝖽(P[1..],T[i+1..i+])𝗁𝖽(P[1..],Q)+𝗁𝖽(Q,T[i+1..i+])8k. Reciprocally, if i is not a multiple of |Q|, then by primitivity of Q we have 𝗁𝖽(Q[1..],Q[i+1..i+])/|Q|62k. Furthermore, by the triangle inequality, 𝗁𝖽(Q[1..],Q[i+1..i+])8k+𝗁𝖽(P[1..],T[i+1..i+]), which implies 𝗁𝖽(P[1..],T[i+1..i+])54k. Consequently, if Q exists, at least 6k of the strings T[p+1..p+q], T[p+q+1..p+2q], …, T[p+(12k1)q+1..p+12kq] are equal to Q, and the majority vote algorithm indeed outputs sk3k(Q) (assuming that neither the 8k-mismatch algorithm nor the algorithm of Corollary 3.2 did not err, which is true w.h.p.).

We finally analyse the complexity of the preprocessing step. The 8k-mismatch pattern matching algorithm (Corollary 3.3) takes O(klog4n) time per character and O(klog2n) space. The algorithm of Corollary 3.2 uses O(log2n) time per character O(klogn) space. Furthermore, O(k) sketches are retrieved, which takes O(k2log2n) time (Corollary 3.2) and maintaining weights requires tw(n) time and ksw(n) space. Finally, the majority vote algorithm takes O(klogn) space and O(klogn) time. In total, the algorithm takes O(k(sw(n)+log2n)) space and O(klog4n+tw(n)+k2log2n) time.

We now apply the lemma above to preprocess Pj as follows. We maintain the 3k-mismatch sketch of T using Corollary 3.2. ˜3.4 ensures that if there are at least K occurrences of Pj in Tj, then there exists a primitive string Q of length q:=|Q|j128k such that 𝗁𝖽(Q,Pj)<2k. For brevity, let λj=(j/q2)q. We apply Lemma 3.12 to Pj and condition on the fact that it outputs q, 𝗌𝗄3k(Q), and w(Q) before or upon the arrival of T[λj]. By an application of ˜3.1, we compute 𝗌𝗄3k(Qλj/q+1) and then 𝖬𝖨(Pj[..λj+q],Qj/q+1) using 𝗌𝗄3k(Pj[..λj+q]). To finish the preprocessing, we compute one more sketch:

Lemma 3.13.

Assume there are K k-mismatch occurrences of Pj in Tj. There is a streaming algorithm that uses O(klog2n+sw(n)) space and O(klog4n+tw(n)) time per character, and computes 𝗌𝗄k(Q[..r]) for r:=n2p(modq) and w(Q[..r]) correctly w.h.p. upon arrival of T[p], where p is the endpoint of the first k-mismatch occurrence of Pj in Tj.

Proof.

By the condition of the lemma, Q is defined and we assume to have computed it by arrival of T[λj], where λj=(j/q2)q and q=|Q|. We run two instances of the k-mismatch algorithm: One for a pattern Pj[..λj] and Tj, and the other for Pj and Tj. Assume that we detect a k-mismatch occurrence of Pj[..λj] ending at a position x. Let r=n2(x+jλj)(modq). We compute 𝗌𝗄k(T[x+1..x+r]) via Corollary 3.2, and w(T[x+1..x+r]) via Proposition 2.9. If p=x+jλj is not the ending position of a k-mismatch occurrence of Pj, we discard the computed information and continue. Otherwise, we have r=r. At the position p the k-mismatch algorithm extracts 𝖬𝖨(T[pj+1..p],Pj) in O(k) time, and we use it to extract 𝖬𝖨(T[x+1..x+r],Q[..r]) from 𝖬𝖨(Pj[..λj+q],Q) in O(k) time as well. Note that the size of the extracted mismatch information is at most 6k by ˜3.4. Finally, we apply ˜3.1 to compute 𝗌𝗄k(Q[..r]) from 𝗌𝗄k(T[x+1..x+r]) and 𝖬𝖨(T[x+1..x+r],Q[..r]) in O(klog2n) time and O(klogn) space. Similarly, with w(T[x+1..x+r]) and the mismatch information, we compute w(Q[..r]) in O(ktw(n)) time and O(sw(n)) space. (See Figure 2 for an illustration.)

Figure 2: When we detect a k-mismatch occurrence of Pj[..λj], we use the next q characters to compute the candidate for 𝗌𝗄k(Q[..r]). If the k-mismatch occurrence of Pj[..λj] extends to a k-mismatch occurrence of Pj, then we keep the candidate sketch.

To show the complexity of the algorithm, we need to understand the structure of the k-mismatch occurrences of Pj[..λj] in Tj. As each k-mismatch occurrence of Pj starts with a k-mismatch occurrence of Pj[..λj], Tj contains at least K k-mismatch occurrences of the latter. Since |Tj|2jj132λj, by ˜3.4 there is a primitive string Q such that |Q|λj128k and 𝗁𝖽(Pj[..λj],(Q))2k. By Lemma 3.5, Q=Q, and again by ˜3.4, the difference between the starting positions of any two k-mismatch occurrences of Pj[1..λj] in Tj is a multiple of q. Therefore, we never process more than two k-mismatch occurrences of Pj[..λj] at a time and the bounds follow.

This information will allow us computing the sketches necessary for Proposition 3.6.

3.4.1 Main phase of the algorithm

The main phase distinguishes two cases: j=1,2 and j3. For j=1,2, we show the following result:

Proposition 3.14.

Assume that j={1,2} and that Pj has more than K=576k k-mismatch occurrences in Tj. The algorithm computes 𝒫kj, 𝖬𝖨(T[p..],T[..np+1]) and w(T[p..]) for p𝒫kj in O(nktw(n)log4n) time and O(k2log2n+sw(n)) space and is correct w.h.p.

Proposition 3.14 can be proven using the same ideas as in the case j3, but needs some additional care because the size of the pattern being large (n/4 or n/2) leads to edge cases that are treated separately. Below, we focus on the case j3. We start by extending Pj into a prefix Pj (Algorithm 1).

Algorithm 1 Extension of Pj into Pj of length j: case j3.

The following inequalities are essential for analysis of correctness of the algorithm:

Proposition 3.15.

For j3, we have j<n and n/2j+11+(j1)n.

Proof.

We start by showing the first inequality:

j<2j+qj(2+1/128k)(8n/27)(2+1/128k)n

To show the second inequality, note that

n/2j+11+j1
n/2n/(3/2)j+1+2n/(3/2)j+qn/2+(4/3+1/128)n/(3/2)jn

We now discuss how to implement Algorithm 1. As we know 𝗌𝗄3k(Q) before or upon the arrival of T[λj], Algorithm 1 can be implemented in streaming via Corollary 3.2, ˜3.1 to use O(klogn+sw(n)) space and O(klog2n+tw(n)) time per character. Furthermore, it always terminates before the arrival of T[n] (Proposition 3.15) and outputs j:=|Pj|, 𝗌𝗄3k(Pj) and w(Pj), and 𝗌𝗄3k(Pj[1..jq]) and w(Pj[1..jq]). Define Tj=T[max{n/2j,1}..n/2j+1+j2]. Note that Tj is well-defined by Proposition 3.15. Furthermore, let Pj′′=[1..jq], j′′=|Pj′′|, and Tj′′=T[n/2j..n/2j+1+j′′2]. From ˜3.7 and Proposition 3.15 we obtain:

Corollary 3.16.

The set 𝒫kj is a subset of the set of the starting positions of k-mismatch occurrences of Pj in Tj, and consequently of the set of the starting positions of k-mismatch occurrences of Pj′′ in Tj′′.

Consider now two subcases depending on the line where Algorithm 1 executes the return.

Return is executed in Line 6
Proposition 3.17.

The prefixes Pj and Pj′′ have the following properties:

  1. 1.

    The number of k-mismatch occurrences of Pj in Tj is O(k).

  2. 2.

    The distance between any two k-mismatch occurrences of Pj′′ in Tj′′ is a multiple of q.

Proof.

To show the first part of the claim, note that jj52j and |Tj|jj+1+j32j. Assume, for sake of contradiction, that there are more than 576k occurrences of Pj in Tj. By ˜3.4, there is a primitive string Q, |Q|j/128k, such that 𝗁𝖽(Pj,(Q))2k. By Lemma 3.5, Q=Q, a contradiction.

We now show the second part of the claim. Note that 23jjqj′′2j and hence |Tj′′|jj+1+j′′32j′′. Next, we have two cases: j′′j and j′′>j. In the first case, every position p which is a starting position of a k-mismatch occurrence of Pj in Tj is also a starting position of a k-mismatch occurrence of Pj′′ in Tj′′. Hence, there are at least K=576k k-mismatch occurrences of Pj′′ in Tj′′, and by ˜3.4, there is a primitive string Q′′, |Q′′|j′′/128k, such that 𝗁𝖽(Pj′′,(Q′′))2k. By Lemma 3.5, Q′′=Q. If j′′>j, then 𝗁𝖽(Pj′′,Q)2k by construction. Consequently, by applying ˜3.4 one more time, we obtain that the difference between the starting positions of any two k-mismatch occurrences of Pj′′ in Tj′′ is q.

We apply the k-mismatch algorithm to detect k-mismatch occurrences of Pj′′ and Pj in the text Tj. In parallel, we maintain two hash tables of size at most K=576k each, Prefj and Sufj, implemented via ˜3.8. When we receive a character T[p], the tables are updated as follows. Assume first that the k-mismatch algorithm detects a new occurrence of Pj′′ ending at the position p. We retrieve 𝗌𝗄3k(T[1..pj′′]) and 𝖬𝖨(Pj′′,T[pj′′+1..p]). From the mismatch information, w(Pj′′) and w(T[..p]) we compute w(T[1..pj′′]), and we memorise t=pj′′ associated with the sketch and the weight for the next q positions. Importantly, at every moment the algorithm stores at most one position-sketch pair by Proposition 3.17. By the definition of Pj′′ and Tj′′, the k-mismatch occurrences detected by the algorithm can only start before n/2, and consequently 2(t+1)n, which implies t+1<nt.

Now, assume that t+1<ntp. In this case, we immediately compute 𝗌𝗄k(T[1..nt]) via the following claim and memorise it for the next q positions:

Proposition 3.18.

Assume to be given 𝗌𝗄k(T[1..t]), 𝗌𝗄k(Q[r..]), and 𝗌𝗄k(Q). There is an algorithm that uses O(klogn) space and O(klog3n) time and computes 𝗌𝗄k(T[1..nt]). The algorithm succeeds w.h.p.

Proof.

By Corollary 3.16 and Proposition 3.17, (nt)t=iq+r for some integer i. Consequently, the sketch can be computed as follows. First, the algorithm computes 𝖬𝖨(Pj′′,T[pj′′+1..p]) and 𝖬𝖨(Pj′′,Q). Secondly, it computes 𝗌𝗄k(QiQ[1..r]) and then deduces 𝗌𝗄k(T[t+1..nt]) in O(klogn) space and O(klog3n) time via ˜3.1. Finally, it computes 𝗌𝗄k(T[1..nt]) from 𝗌𝗄k(T[1..t]) and 𝗌𝗄k(T[t+1..nt]).

Also, if the current position p equals nt, where t is the position in the stored position-sketch pair, we memorise 𝗌𝗄k(T[1..nt]). Again, by Proposition 3.17 the algorithm stores at most one sketch at a time. If the current position p is the endpoint of a k-mismatch occurrence of Pj in Tj, the position pq is necessarily the endpoint of a k-mismatch occurrence of Pj′′ in Tj′′, and we store t=pqj′′ associated with 𝗌𝗄k(T[1..t]) and w(T[1..t]). We add this triple to Prefj. In addition, if ntp, we have already computed 𝗌𝗄k(T[1..nt]), and we add it to Sufj. Finally, if p is the current position and for t=np we have (t,𝗌𝗄k(T[1..t]),w(T[1..t]))Prefj, we add p associated with 𝗌𝗄k(T[1..p]) to Sufj.

If any of the insertions takes more than constant time or if the size of any of Prefj and Sufj becomes larger than K, the algorithm terminates and returns .

When the entire string T has arrived, the algorithm considers each position tPrefj, extracts 𝗌𝗄k(T[1..t]),w(T[1..t]) from Prefj and 𝗌𝗄k(T[1..nt]) from Sufj and if t passes the test of Proposition 3.6, reports t+1 as a k-mismatch period of T, and also returns w(T[t+1..])=w(T)w(T[1..t]) (undefined if one of the values on the right is undefined), and 𝖬𝖨(T[t+1..],T[..nt]).

Return is executed in Line 7
Proposition 3.19.

If return is executed in Line 7, we have 𝗁𝖽(Pj,Q)<2k and for all t[n/2j..n/2j+11] there is n/2ntn/2j+(j+2).

Proof.

The first part of the claim is immediate by construction. To show the second part, recall that j2j. Hence,

n/2ntnn/2+j+1n/2j+(2j+2)n/2j+(j+2)

We run the k-mismatch algorithm (Corollary 3.3) for Pj and Tj. If a position p is the endpoint of the first k-mismatch occurrence of Pj in Tj, we retrieve 𝗌𝗄k(T[1..pj]) and 𝖬𝖨(T[pj+1..p],Pj), and deduce w(T[1..pj]) with the same method as in the previous case. Also, we memorise p, the sketch, the mismatch information and the weight. We would now like to process the last k-mismatch occurrence of Pj in Tj in a similar way. As it is not possible to say in advance whether the current k-mismatch occurrence is the last one, we instead do the following. Starting from the second endpoint p of a k-mismatch occurrence of Pj in Tj, we retrieve 𝖬𝖨(T[pj+1..p],Pj) by Corollary 3.3, and memorise p and the mismatch information until the next k-mismatch occurrence is detected, when they are discarded. Additionally, at the position p+1 we launch a new instance of the algorithm of Corollary 3.2, maintaining 𝗌𝗄k(T[p+1..]). Again, if we detect another k-mismatch occurrence, we discard the currently stored sketch. In addition, when T[x] arrives, for x{n/2j+(j+1),n/2j+(j+2)} we launch a new instance of the algorithm in Corollary 3.2, maintaining 𝗌𝗄k(T[x+1..]). This way, when we reach the end of T, we have the following information at hand:

  1. 1.

    For the endpoint p of the first k-mismatch occurrence of Pj in Tj, 𝗌𝗄k(T[1..pj]), weight w(T[1..pj]), and the mismatch information 𝖬𝖨(T[pj+1..p],Pj);

  2. 2.

    For the endpoint p of the last k-mismatch occurrence of Pj in Tj, the mismatch information 𝖬𝖨(T[pj+1..p],Pj) and 𝗌𝗄k(T[p+1..]);

  3. 3.

    𝗌𝗄k(T[x+1..]) for x{n/2j+(2j+1),n/2j+(2j+2)}.

Figure 3: If Algorithm 1 executes return in Line 7, 𝒫jk{pj+1,p+qj+1,,pj+1}. To test each position in the latter set, we exploit the structure of T[pj+1..pj+1] (shown in red, with crosses marking mismatches between it and Q).

By Proposition 3.19 and ˜3.4, we have 𝒫jk{pj+1,p+qj+1,,pj+1}. We test each position t in the latter set as follows (see Figure 3):

  1. 1.

    Compute 𝗌𝗄k(T[t..]). First, retrieve 𝗌𝗄k(T[1..t1]) from sketches 𝗌𝗄k(T[1..pj]) and 𝗌𝗄k(Q(tp)/q), and the mismatch information 𝖬𝖨(T[pj+1..p],Pj), 𝖬𝖨(T[pj+1..p],Pj), and 𝖬𝖨(Pj,Q) in O(klog2n) time and O(klogn) space via ˜3.1. Second, compute 𝗌𝗄k(T[t..]) from 𝗌𝗄k(T) and 𝗌𝗄k(T[1..t1]) in O(klog2n) time and O(klogn) space via another application of ˜3.1.

  2. 2.

    Compute w(T[t..]). First, retrieve w(T[1..t1]) from w(T[1..pj]) and w(Q(tp)/q)=[(tp)/q]w(Q), and the mismatch information 𝖬𝖨(T[pj+1..p],Pj), 𝖬𝖨(T[pj+1..p],Pj), and 𝖬𝖨(Pj,Q) in O(ktw(n)) time and sw(n) space. Second, compute w(T[t..])=w(T)w(T[1..t1]) (undefined if one of the values on the right is undefined).

  3. 3.

    Compute 𝗌𝗄k(T[1..nt+1]). If nt+1{n/2j+(j+1),n/2j+(j+2)}, we already know the sketch. Otherwise, by Proposition 3.19 n/2nt+1n/2+j. Additionally, (nt+1)(pj+1)+1=qi+r for an integer r defined as in Lemma 3.13. Hence, 𝗌𝗄k(T[1..nt+1]) can be computed via ˜3.1: start by computing 𝗌𝗄k(T[pj+1..nt+1]) from 𝗌𝗄k(Q), 𝗌𝗄k(Q[1..r]), and the mismatch information for p and p, and then use 𝗌𝗄k(T[1..pj]) to compute 𝗌𝗄k(T[1..nt]).

  4. 4.

    Compute 𝗁𝖽k(T[t..n],T[1..nt+1]) using the computed sketches via ˜3.1. If it is at most k, output t as a k-mismatch period, and return w(T[t..]) and 𝖬𝖨(T[t..],T[..nt+1]).

Proposition 3.20.

Assume that j3 and that Pj has more than K=576k k-mismatch occurrences in Tj. The algorithm computes 𝒫kj, 𝖬𝖨(T[p..],T[..np+1]) and w(T[p..]) for p𝒫kj in O(nktw(n)log4n) time and O(k2log2n+sw(n)) space and is correct w.h.p.

Proof.

The preprocessing of Pj takes O(n(klog4n+tw(n))) time and O(klog2n+sw(n)) space. The main phase of the algorithm starts with an extension procedure (Algorithm 1), which takes O(n(klog2n+tw(n))) total time and O(klogn+sw(n)) space. If the return is executed in Line 6 of Algorithm 1, the algorithm then runs two instances of the k-mismatch algorithm (Corollary 3.3) that take O(nklog4n) time and O(klog2n) space. Adding elements to Prefj and Sufj, as well as look-ups, takes O(1) time per element, and we add at most K=O(k) elements in total. The two hash tables occupy O(k2log2n) space (˜3.8, ˜3.1). Finally, testing all candidate positions requires O(Kklog3n) time and O(klogn) space (Proposition 3.6). If the return is executed in Line 7 of Algorithm 1, the algorithm runs an instance of the k-mismatch algorithm, which takes O(nklog4n) time and O(klog2n) space, and maintains a constant number of sketches, taking O(nlog2n) time and O(klogn) space. The process to test the candidate k-periods uses O(klogn+sw(n)) space and O(k(log3n+tw(n))) time, and it is iterated n times.

The algorithm can fail if the preprocessing fails, if the k-mismatch algorithm errs, or if adding an element to the hash tables takes more than constant time, or if the test fails. By the union bound, Corollary 3.3, ˜3.1, and Proposition 3.6, the failure probability is inverse-polynomial in n.

References

  • [1] Gabriel Bathie, Tomasz Kociumaka, and Tatiana Starikovskaya. Small-space algorithms for the online language distance problem for palindromes and squares. In ISAAC 2023, volume 283 of LIPIcs, pages 10:1–10:17, 2023. doi:10.4230/LIPICS.ISAAC.2023.10.
  • [2] Michael A. Bender, Martín Farach-Colton, John Kuszmaul, and William Kuszmaul. Modern hashing made simple. In SOSA 2024, pages 363–373, 2024. doi:10.1137/1.9781611977936.33.
  • [3] Petra Berenbrink, Funda Ergün, Frederik Mallmann-Trenn, and Erfan Sadeqi Azer. Palindrome recognition in the streaming model. In STACS 2014, volume 25, pages 149–161, 2014. doi:10.4230/LIPIcs.STACS.2014.149.
  • [4] Sudatta Bhattacharya and Michal Koucký. Locally consistent decomposition of strings with applications to edit distance sketching. In STOC 2023, pages 219–232, 2023. doi:10.1145/3564246.3585239.
  • [5] Sudatta Bhattacharya and Michal Koucký. Streaming k-edit approximate pattern matching via string decomposition. In ICALP 2023, volume 261 of LIPIcs, pages 22:1–22:14, 2023. doi:10.4230/LIPICS.ICALP.2023.22.
  • [6] Sudatta Bhattacharya and Michal Koucký. Locally consistent decomposition of strings with applications to edit distance sketching, 2023. doi:10.48550/arXiv.2302.04475.
  • [7] Robert S. Boyer and J Strother Moore. MJRTY: A fast majority vote algorithm. In Automated Reasoning: Essays in Honor of Woody Bledsoe, Automated Reasoning Series, pages 105–118. Kluwer Academic Publishers, 1991.
  • [8] Panagiotis Charalampopoulos, Tomasz Kociumaka, and Philip Wellnitz. Faster approximate pattern matching: A unified approach. In FOCS 2020, pages 978–989. IEEE, 2020. doi:10.1109/FOCS46700.2020.00095.
  • [9] Raphaël Clifford, Tomasz Kociumaka, and Ely Porat. The streaming k-mismatch problem. In SODA 2019, pages 1106–1125. SIAM, 2019. doi:10.1137/1.9781611975482.68.
  • [10] Richard Cole and Ramesh Hariharan. Approximate string matching: A simpler faster algorithm. In Howard J. Karloff, editor, SODA 1998, pages 463–472. ACM/SIAM, 1998. URL: http://dl.acm.org/citation.cfm?id=314613.314827.
  • [11] Mohamed G. Elfeky, Walid G. Aref, and Ahmed K. Elmagarmid. Stagger: Periodicity mining of data streams using expanding sliding windows. In ICDM 2006, pages 188–199, 2006. doi:10.1109/ICDM.2006.153.
  • [12] Funda Ergün, Elena Grigorescu, Erfan Sadeqi Azer, and Samson Zhou. Streaming periodicity with mismatches. In APPROX/RANDOM 2017, volume 81 of LIPIcs, pages 42:1–42:21, 2017. doi:10.4230/LIPICS.APPROX-RANDOM.2017.42.
  • [13] Funda Ergün, Elena Grigorescu, Erfan Sadeqi Azer, and Samson Zhou. Periodicity in data streams with wildcards. Theory Comput. Syst., 64(1):177–197, 2020. doi:10.1007/S00224-019-09950-Y.
  • [14] Funda Ergun, Hossein Jowhari, and Mert Sağlam. Periodicity in streams. In APPROX/RANDOM 2010, pages 545–559, 2010.
  • [15] Funda Ergün, Elena Grigorescu, Erfan Sadeqi Azer, and Samson Zhou. Streaming periodicity with mismatches, 2017. arXiv:1708.04381.
  • [16] Pawel Gawrychowski, Oleg Merkurev, Arseny M. Shur, and Przemyslaw Uznanski. Tight tradeoffs for real-time approximation of longest palindromes in streams. Algorithmica, 81(9):3630–3654, 2019. doi:10.1007/s00453-019-00591-8.
  • [17] Tomohiro I. Longest Common Extensions with Recompression. In CPM 2017, volume 78 of LIPIcs, pages 18:1–18:15, 2017. doi:10.4230/LIPIcs.CPM.2017.18.
  • [18] John C. Kieffer and En-Hui Yang. Grammar-based codes: A new class of universal lossless source codes. IEEE Trans. Inf. Theory, 46(3):737–754, 2000. doi:10.1109/18.841160.
  • [19] Gad M. Landau and Uzi Vishkin. Fast string matching with k differences. Journal of Computer and System Sciences, 37(1):63–78, 1988. doi:10.1016/0022-0000(88)90045-1.
  • [20] Markus Lohrey. Algorithmics on slp-compressed strings: A survey. Groups Complex. Cryptol., 4(2):241–299, 2012. doi:10.1515/GCC-2012-0016.
  • [21] Oleg Merkurev and Arseny M. Shur. Computing the maximum exponent in a stream. Algorithmica, 84(3):742–756, 2022. doi:10.1007/s00453-021-00883-y.
  • [22] Rasmus Pagh and Flemming Friche Rodler. Cuckoo hashing. J. Algorithms, 51(2):122–144, 2004. doi:10.1016/J.JALGOR.2003.12.002.

Appendix A A gap in the previous streaming algorithm for computing 𝒌-mismatch periods

In this section, we point to the specific claim in the correctness proof of the previous streaming algorithm for computing k-mismatch periods [15] which is, in our opinion, not true.

Let S be a string length n, and 1p<qn2 two k-mismatch periods of S such that k(p+q)in2k(p+q), where i is a position of S, and q(2k+1)gcd(p,q). The construction of [15] introduces a grid defined over a set {k,,k}2. A node (a,b) of the grid represents a position i+ap+bq of S. For a node representing a position j, we add edges connecting it to nodes representing j+p, j+q, jp, and jq (if they exist in the grid). Finally, we say that an edge (i,j) of the gird is bad if S[i]S[j].

The proof of [15, Theorem 28], one of the key elements of the streaming algorithm of Ergün et al., relies on the fact that there are a few bad edges in the grid. One of the steps in their proof of this fact is the following claim:

Proposition A.1 ([15, Claim 20]).

The nodes of the grid correspond to distinct positions of S.

As an immediate corollary, and since p and q are both k-mismatch periods of S, they immediately derive that there are at most 2k bad edges in the grid.

The authors then extend their approach to the case when S has m k-mismatch periods p1<<pm, where pm(2k+1)gcd(p1,pm). One can construct an m-dimensional grid in a similar way to the case m=2, and it is claimed that in this grid, “the total number of bad edges is at most mk” (Page 21). However, consider the string S=a40ba60. All integers smaller than 50 are 2-mismatch periods of S, and in this example we have m=50, k=2 and gcd(1,50)=1, verifying the assumption 50(2k+1)gcd(1,50). Let {2,,2}50 be the grid centred around the index 41 (i.e the only character b). Similarly to the case m=2, a point (a1,,a50) of the grid represents the position 41+iai, and an edge between nodes representing positions i,j is bad if S[i]S[j]. Note for any i25, the node (a1,,a50) with ai=2, a2i=1 and aj=0 for j{i,2i} represents the position 41+2i2i=41. As a result, 41 is represented by at least distinct 25 different nodes in the grid, which contradicts Proposition A.1 for m2. Furthermore, these nodes are connected with each of their neighbours with a bad edge. Since each node has at least 5 neighbours, there are at least 125 distinct bad edges, contradicting the upper bound on the number of bad edges which was mk=100.