You are given a 0-indexed string s
. You are also given a 0-indexed string queryCharacters
of length k
and a 0-indexed array of integer indices queryIndices
of length k
, both of which are used to describe k
queries.
The ith
query updates the character in s
at index queryIndices[i]
to the character queryCharacters[i]
.
Return an array lengths
of length k
where lengths[i]
is the length of the longest substring of s
consisting of only one repeating character after the ith
query is performed.
Example 1:
Input: s = "babacc", queryCharacters = "bcb", queryIndices = [1,3,3] Output: [3,3,4] Explanation: - 1st query updates s = "bbbacc". The longest substring consisting of one repeating character is "bbb" with length 3. - 2nd query updates s = "bbbccc". The longest substring consisting of one repeating character can be "bbb" or "ccc" with length 3. - 3rd query updates s = "bbbbcc". The longest substring consisting of one repeating character is "bbbb" with length 4. Thus, we return [3,3,4].
Example 2:
Input: s = "abyzz", queryCharacters = "aa", queryIndices = [2,1] Output: [2,3] Explanation: - 1st query updates s = "abazz". The longest substring consisting of one repeating character is "zz" with length 2. - 2nd query updates s = "aaazz". The longest substring consisting of one repeating character is "aaa" with length 3. Thus, we return [2,3].
Constraints:
1 <= s.length <= 105
s
consists of lowercase English letters.k == queryCharacters.length == queryIndices.length
1 <= k <= 105
queryCharacters
consists of lowercase English letters.0 <= queryIndices[i] < s.length
This problem requires finding the length of the longest substring containing only one repeating character after each query. A segment tree is an efficient data structure to solve this.
Approach:
We use a segment tree to efficiently handle updates and queries on the string. Each node in the segment tree represents a substring of s
. The key information stored in each node is:
lmx
: Length of the longest repeating character substring starting from the left end of the node's range.rmx
: Length of the longest repeating character substring ending at the right end of the node's range.mx
: Length of the longest repeating character substring within the node's range.Algorithm:
Build Segment Tree: Construct a segment tree from the initial string s
. For leaf nodes (representing single characters), lmx
, rmx
, and mx
are all 1. For internal nodes, these values are calculated recursively by combining the information from their children. The combination considers whether the last character of the left child's substring matches the first character of the right child's substring.
Process Queries: Iterate through the queryCharacters
and queryIndices
. For each query:
queryIndices[i]
to queryCharacters[i]
. This update propagates up the tree, recalculating lmx
, rmx
, and mx
for affected nodes.mx
, which represents the length of the longest repeating character substring in the updated string. Append this value to the lengths
array.Return: Return the lengths
array containing the length of the longest repeating substring after each query.
Time Complexity:
Space Complexity:
lengths
array takes O(k) space.Code (Python):
The provided Python code implements this approach using a SegmentTree
class. The build
, modify
, query
, and pushup
methods handle the segment tree operations. The Solution
class processes the queries and returns the lengths
array. The code includes detailed comments for better understanding.
Other Languages:
The problem solution is also provided in Java, C++, and TypeScript, demonstrating the adaptability of the segment tree approach across different programming languages. The logic remains the same across all the solutions, focusing on efficiently managing updates and queries using a segment tree to obtain the desired result in optimal time complexity.