Talentd
FleetCode
Make and follow sheets.Sign in

Longest Substring of One Repeating Character solution and explanation

HardArrayOrdered SetSegment TreeString8 min read65.8% acceptanceUpdated 9 Apr 2026
Leetcode Weekly 285 | 2213. Longest Substring of One Repeating CharactercodingMohan · 25:07 · 2K viewsWatch on YouTube
4 more videos on this problem
  1. Leetcode Weekly 285 | 2213. Longest Substring of One Repeating CharactercodingMohan · 25:07 · 2K views
  2. Longest Substring Of One Repeating Character || LeetCode Weekly Contest 285 || Problem DCompetitive Coding - Newton School · 17:50 · 1K views
  3. 【每日一题】LeetCode 2213. Longest Substring of One Repeating CharacterHuifeng Guan · 34:58 · 638 views
  4. 2213. Longest Substring of One Repeating Character (Leetcode Hard)Programming Live with Larry · 1:20:57 · 474 views
  5. LeetCode 2213: Longest Substring of One Repeating CharacterAlitaCode · 31:46 · 31 views

The problem

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

Approach overview

Problem Overview: You start with a string s. Each query updates a single index with a new character. After every update, return the length of the longest substring consisting of only one repeating character. The challenge is efficiently recomputing this value after each modification.

Approach 1: Naive Approach with Recalculation (O(n) per query, O(1) space)

After each character update, recompute the longest repeating substring by scanning the entire string. Iterate through s while tracking the length of the current run of identical characters and the global maximum. Whenever the character changes, reset the run counter and continue. This approach uses only a few variables and works for any string size, but every query forces a full pass over the array. If there are q updates and the string length is n, the total complexity becomes O(n * q). It’s simple and reliable but too slow when both n and q are large.

Approach 2: Optimized Sliding Window Style Scan (O(n) per query, O(1) space)

A more structured scan treats consecutive identical characters as windows. Maintain two pointers representing the current run of repeating characters. As you iterate through the string, extend the window while characters match and shrink/reset when they differ. Each update modifies only one index, so the string is scanned once to rebuild the longest run information. The key idea is tracking run lengths directly instead of evaluating all possible substrings. This keeps the logic linear and avoids redundant comparisons. Although each query still requires an O(n) pass, the implementation is clean and predictable, making it suitable when constraints are moderate.

For very large constraints, production-grade solutions typically rely on a segment tree that stores prefix, suffix, and maximum repeating lengths for each segment of the array. Updates then take O(log n). The simplified approaches here focus on clarity and correctness rather than advanced tree structures.

Recommended for interviews: Start with the naive recalculation approach to demonstrate understanding of the problem and how repeating segments are detected. Then discuss how repeated scans become expensive with many queries. Interviewers usually expect you to mention a segment tree or interval-based structure for O(log n) updates. Showing the progression from brute force scanning to a structured data structure demonstrates both problem-solving clarity and optimization awareness.

Approach 1: Naive Approach with Recalculation

In this approach, after each query update, we recalculate the longest substring consisting of one repeating character for the entire string. Though simple and direct, this method can be inefficient for large strings since it checks the entire string after every update.
def max_consecutive_chars(s):
    max_len = 0
    current_len = 1
    for i in range(1, len(s)):
        if s[i] == s[i - 1]:
            current_len += 1
        else:
            max_len = max(max_len, current_len)
            current_len = 1
    return max(max_len, current_len)


def longest_substring_after_queries(s, query_characters, query_indices):
    result = []
    s = list(s)
    for i in range(len(query_indices)):
        s[query_indices[i]] = query_characters[i]
        result.append(max_consecutive_chars(s))
    return result

# Example usage
s = "babacc"
query_characters = "bcb"
query_indices = [1, 3, 3]
print(longest_substring_after_queries(s, query_characters, query_indices))
import java.util.*;

public class LongestSubstring {
    public static int maxRepeatedCharLength(String s) {
        int maxLength = 0, currentLength = 1;
        for (int i = 1; i < s.length(); i++) {
            if (s.charAt(i) == s.charAt(i - 1)) {
                currentLength++;
            } else {
                maxLength = Math.max(maxLength, currentLength);
                currentLength = 1;
            }
        }
        return Math.max(maxLength, currentLength);
    }

    public static int[] longestSubstringAfterQueries(String s, String queryCharacters, int[] queryIndices) {
        int[] result = new int[queryIndices.length];
        StringBuilder sb = new StringBuilder(s);

        for (int i = 0; i < queryIndices.length; i++) {
            sb.setCharAt(queryIndices[i], queryCharacters.charAt(i));
            result[i] = maxRepeatedCharLength(sb.toString());
        }

        return result;
    }

    public static void main(String[] args) {
        String s = "babacc";
        String queryCharacters = "bcb";
        int[] queryIndices = {1, 3, 3};

        int[] result = longestSubstringAfterQueries(s, queryCharacters, queryIndices);
        System.out.println(Arrays.toString(result));
    }
}
#include <iostream>
#include <string>
#include <vector>

int getMaxSubstringLength(std::string &s) {
    int maxLength = 0, currentLength = 1;
    for (size_t i = 1; i < s.size(); ++i) {
        if (s[i] == s[i - 1]) {
            currentLength++;
        } else {
            maxLength = std::max(maxLength, currentLength);
            currentLength = 1;
        }
    }
    return std::max(maxLength, currentLength);
}

std::vector<int> longestSubstringAfterQueries(std::string s, std::string queryCharacters, std::vector<int> queryIndices) {
    std::vector<int> result(queryIndices.size());
    for (size_t i = 0; i < queryIndices.size(); ++i) {
        s[queryIndices[i]] = queryCharacters[i];
        result[i] = getMaxSubstringLength(s);
    }
    return result;
}

int main() {
    std::string s = "babacc";
    std::string queryCharacters = "bcb";
    std::vector<int> queryIndices = {1, 3, 3};
    std::vector<int> result = longestSubstringAfterQueries(s, queryCharacters, queryIndices);
    for (int len : result) {
        std::cout << len << " ";
    }
    return 0;
}
function getMaxSubStringLength(s) {
    let maxLen = 0, currentLen = 1;
    for (let i = 1; i < s.length; i++) {
        if (s[i] === s[i - 1]) {
            currentLen++;
        } else {
            maxLen = Math.max(maxLen, currentLen);
            currentLen = 1;
        }
    }
    return Math.max(maxLen, currentLen);
}

function longestSubstringAfterQueries(s, queryCharacters, queryIndices) {
    const results = [];
    s = s.split("");
    queryIndices.forEach((index, i) => {
        s[index] = queryCharacters[i];
        results.push(getMaxSubStringLength(s.join("")));
    });
    return results;
}

// Example usage
let s = "babacc";
let queryCharacters = "bcb";
let queryIndices = [1, 3, 3];
console.log(longestSubstringAfterQueries(s, queryCharacters, queryIndices));
#include <stdio.h>
#include <string.h>

int maxConsecutiveChars(char *str, int len) {
    int maxLen = 0, currentLen = 1;
    for (int i = 1; i < len; i++) {
        if (str[i] == str[i - 1]) {
            currentLen++;
        } else {
            if (currentLen > maxLen) maxLen = currentLen;
            currentLen = 1;
        }
    }
    if (currentLen > maxLen) maxLen = currentLen;
    return maxLen;
}

void longestSubstringAfterQueries(char *s, char *queryCharacters, int *queryIndices, int k, int *output) {
    int length = strlen(s);
    for (int i = 0; i < k; i++) {
        s[queryIndices[i]] = queryCharacters[i];
        output[i] = maxConsecutiveChars(s, length);
    }
}

int main() {
    char s[] = "babacc";
    char queryCharacters[] = "bcb";
    int queryIndices[] = {1, 3, 3};
    int k = 3;
    int output[k];
    longestSubstringAfterQueries(s, queryCharacters, queryIndices, k, output);
    for (int i = 0; i < k; i++) {
        printf("%d ", output[i]);
    }
    return 0;
}
using System;

class LongestSubstring {
    static int MaxRepeatedCharLength(string s) {
        int maxLength = 0, currentLength = 1;
        for (int i = 1; i < s.Length; i++) {
            if (s[i] == s[i - 1]) {
                currentLength++;
            } else {
                maxLength = Math.Max(maxLength, currentLength);
                currentLength = 1;
            }
        }
        return Math.Max(maxLength, currentLength);
    }

    static int[] LongestSubstringAfterQueries(string s, string queryCharacters, int[] queryIndices) {
        char[] chars = s.ToCharArray();
        int[] result = new int[queryIndices.Length];

        for (int i = 0; i < queryIndices.Length; i++) {
            chars[queryIndices[i]] = queryCharacters[i];
            result[i] = MaxRepeatedCharLength(new string(chars));
        }

        return result;
    }

    static void Main() {
        string s = "babacc";
        string queryCharacters = "bcb";
        int[] queryIndices = {1, 3, 3};
        int[] result = LongestSubstringAfterQueries(s, queryCharacters, queryIndices);

        Console.WriteLine(string.Join(", ", result));
    }
}

In the Python implementation, we convert the string to a list for in-place character updates. After each query, we modify the string and use a utility function to determine the length of the longest contiguous characters.

Complexity

Time Complexity: O(k * n), iterating over the string for each query.
Space Complexity: O(1) for additional data structures, beyond space for result storage.

Try this approach in the editor

Approach 2: Optimized Sliding Window Approach

This approach employs a sliding window technique to more efficiently handle the string updates. By using two pointers, we limit recalculations to the affected region after each query, improving performance over the naive approach.
def update_and_find_max(s, index, new_char, max_len):
    s[index] = new_char
    left = right = index

    while left - 1 >= 0 and s[left - 1] == s[index]:
        left -= 1
    while right + 1 < len(s) and s[right + 1] == s[index]:
        right += 1

    current_len = right - left + 1
    max_len[0] = max(max_len[0], current_len)


def longest_substring_after_queries(s, query_characters, query_indices):
    s = list(s)
    max_len = [1]
    update_and_find_max(s, 0, s[0], max_len)
    result = []

    for idx, char in zip(query_indices, query_characters):
        update_and_find_max(s, idx, char, max_len)
        result.append(max_len[0])

    return result


s = "babacc"
query_characters = "bcb"
query_indices = [1, 3, 3]
print(longest_substring_after_queries(s, query_characters, query_indices))
import java.util.*;

public class LongestSubstring {
    private static void updateAndFindMax(char[] s, int index, char newChar, int[] maxLen) {
        int len = s.length;
        int left = index, right = index;
        s[index] = newChar;

        while (left - 1 >= 0 && s[left - 1] == s[index]) left--;
        while (right + 1 < len && s[right + 1] == s[index]) right++;

        int currLen = right - left + 1;
        maxLen[0] = Math.max(maxLen[0], currLen);
    }

    public static int[] longestSubstringAfterQueries(String s, String queryCharacters, int[] queryIndices) {
        int[] maxLen = {1};
        char[] charArray = s.toCharArray();
        updateAndFindMax(charArray, 0, charArray[0], maxLen);

        int[] result = new int[queryIndices.length];
        for (int i = 0; i < queryIndices.length; i++) {
            updateAndFindMax(charArray, queryIndices[i], queryCharacters.charAt(i), maxLen);
            result[i] = maxLen[0];
        }
        return result;
    }

    public static void main(String[] args) {
        String s = "babacc";
        String queryCharacters = "bcb";
        int[] queryIndices = {1, 3, 3};
        int[] result = longestSubstringAfterQueries(s, queryCharacters, queryIndices);
        System.out.println(Arrays.toString(result));
    }
}
#include <iostream>
#include <string>
#include <vector>

void updateAndFindMax(std::string &s, int index, char newChar, int &maxLen) {
    int len = s.length();
    int left = index, right = index;
    s[index] = newChar;

    while (left - 1 >= 0 && s[left - 1] == s[index]) left--;
    while (right + 1 < len && s[right + 1] == s[index]) right++;

    int currLen = right - left + 1;
    maxLen = std::max(maxLen, currLen);
}

std::vector<int> longestSubstringAfterQueries(std::string s, std::string queryCharacters, std::vector<int> queryIndices) {
    int initMaxLen = 1;
    updateAndFindMax(s, 0, s[0], initMaxLen);
    std::vector<int> result(queryIndices.size());

    for (size_t i = 0; i < queryIndices.size(); i++) {
        updateAndFindMax(s, queryIndices[i], queryCharacters[i], initMaxLen);
        result[i] = initMaxLen;
    }
    return result;
}

int main() {
    std::string s = "babacc";
    std::string queryCharacters = "bcb";
    std::vector<int> queryIndices = {1, 3, 3};
    std::vector<int> result = longestSubstringAfterQueries(s, queryCharacters, queryIndices);
    for (int length : result) {
        std::cout << length << " ";
    }
    return 0;
}
function updateAndFindMax(s, index, newChar, maxLen) {
    s[index] = newChar;
    let left = index, right = index;

    while (left - 1 >= 0 && s[left - 1] === s[index]) left--;
    while (right + 1 < s.length && s[right + 1] === s[index]) right++;

    const currentLen = right - left + 1;
    maxLen[0] = Math.max(maxLen[0], currentLen);
}

function longestSubstringAfterQueries(s, queryCharacters, queryIndices) {
    const arr = s.split("");
    const maxLen = [1];
    updateAndFindMax(arr, 0, arr[0], maxLen);
    const results = [];

    queryIndices.forEach((q, i) => {
        updateAndFindMax(arr, q, queryCharacters[i], maxLen);
        results.push(maxLen[0]);
    });
    return results;
}

// Example usage
const s = "babacc";
const queryCharacters = "bcb";
const queryIndices = [1, 3, 3];
console.log(longestSubstringAfterQueries(s, queryCharacters, queryIndices));
#include <stdio.h>
#include <string.h>

void updateAndFindMax(char *s, int index, char newChar, int *maxLen) {
    int len = strlen(s);
    int left = index, right = index;
    s[index] = newChar;

    while (left - 1 >= 0 && s[left - 1] == s[index]) left--;
    while (right + 1 < len && s[right + 1] == s[index]) right++;

    int currLen = right - left + 1;
    if (currLen > *maxLen) *maxLen = currLen;
}

void longestSubstringAfterQueries(char *s, char *queryCharacters, int *queryIndices, int k, int *output) {
    int initMaxLen = 1;
    updateAndFindMax(s, 0, s[0], &initMaxLen);

    for (int i = 0; i < k; i++) {
        updateAndFindMax(s, queryIndices[i], queryCharacters[i], &initMaxLen);
        output[i] = initMaxLen;
    }
}

int main() {
    char s[] = "babacc";
    char queryCharacters[] = "bcb";
    int queryIndices[] = {1, 3, 3};
    int k = 3;
    int output[k];
    longestSubstringAfterQueries(s, queryCharacters, queryIndices, k, output);
    for (int i = 0; i < k; i++) {
        printf("%d ", output[i]);
    }
    return 0;
}
using System;

class LongestSubstring {
    static void UpdateAndFindMax(char[] s, int index, char newChar, ref int maxLen) {
        s[index] = newChar;
        int left = index, right = index;

        while (left - 1 >= 0 && s[left - 1] == s[index]) left--;
        while (right + 1 < s.Length && s[right + 1] == s[index]) right++;

        int currentLen = right - left + 1;
        maxLen = Math.Max(maxLen, currentLen);
    }

    static int[] LongestSubstringAfterQueries(string s, string queryCharacters, int[] queryIndices) {
        char[] chars = s.ToCharArray();
        int maxLen = 1;
        UpdateAndFindMax(chars, 0, chars[0], ref maxLen);

        int[] result = new int[queryIndices.Length];

        for (int i = 0; i < queryIndices.Length; i++) {
            UpdateAndFindMax(chars, queryIndices[i], queryCharacters[i], ref maxLen);
            result[i] = maxLen;
        }
        return result;
    }

    static void Main() {
        string s = "babacc";
        string queryCharacters = "bcb";
        int[] queryIndices = {1, 3, 3};
        int[] result = LongestSubstringAfterQueries(s, queryCharacters, queryIndices);

        Console.WriteLine(string.Join(", ", result));
    }
}

In Python, the list and tuple approach ensures mutable updates and controlled indices dictating where recalibrations on substring size need be implemented and observed, syncing memory savings and efficiency.

Complexity

Time Complexity: O(k * m), m being fixed to targeted local regions per update.
Space Complexity: O(1) outside the output holding structure.

Try this approach in the editor

Approach 3: Segment Tree

The segment tree divides the entire interval into multiple non-continuous sub-intervals, and the number of sub-intervals does not exceed log(width). To update the value of an element, you only need to update log(width) intervals, and these intervals are all contained in a large interval that contains the element. When modifying the interval, you need to use lazy tags to ensure efficiency.

  • Each node of the segment tree represents an interval;
  • The segment tree has a unique root node, which represents the entire statistical range, such as [1, n];
  • Each leaf node of the segment tree represents an elementary interval of length 1, [x, x];
  • For each internal node [l, r], its left child is [l, mid], and the right child is [mid + 1, r], where mid = \frac{l + r}{2};

For this problem, the information maintained by the segment tree node includes:

  1. The number of longest consecutive characters in the prefix, lmx;
  2. The number of longest consecutive characters in the suffix, rmx;
  3. The number of longest consecutive characters in the interval, mx.
  4. The left endpoint l and the right endpoint r of the interval.

The time complexity is O(n times log n), and the space complexity is O(n times log n). Where n is the length of the string s.

class Node {
    l: number;
    r: number;
    lmx: number;
    rmx: number;
    mx: number;

    constructor(l: number, r: number) {
        this.l = l;
        this.r = r;
        this.lmx = 1;
        this.rmx = 1;
        this.mx = 1;
    }
}

class SegmentTree {
    private s: string[];
    private tr: Node[];

    constructor(s: string) {
        this.s = s.split('');
        this.tr = Array(s.length * 4)
            .fill(null)
            .map(() => new Node(0, 0));
        this.build(1, 1, s.length);
    }

    private build(u: number, l: number, r: number): void {
        this.tr[u] = new Node(l, r);
        if (l === r) {
            return;
        }
        const mid = (l + r) >> 1;
        this.build(u << 1, l, mid);
        this.build((u << 1) | 1, mid + 1, r);
        this.pushup(u);
    }

    public modify(u: number, x: number, v: string): void {
        if (this.tr[u].l === x && this.tr[u].r === x) {
            this.s[x - 1] = v;
            return;
        }
        const mid = (this.tr[u].l + this.tr[u].r) >> 1;
        if (x <= mid) {
            this.modify(u << 1, x, v);
        } else {
            this.modify((u << 1) | 1, x, v);
        }
        this.pushup(u);
    }

    public query(u: number, l: number, r: number): number {
        if (this.tr[u].l >= l && this.tr[u].r <= r) {
            return this.tr[u].mx;
        }
        const mid = (this.tr[u].l + this.tr[u].r) >> 1;
        let ans = 0;
        if (r <= mid) {
            ans = this.query(u << 1, l, r);
        } else if (l > mid) {
            ans = Math.max(ans, this.query((u << 1) | 1, l, r));
        } else {
            ans = Math.max(this.query(u << 1, l, r), this.query((u << 1) | 1, l, r));
        }
        return ans;
    }

    private pushup(u: number): void {
        const root = this.tr[u];
        const left = this.tr[u << 1];
        const right = this.tr[(u << 1) | 1];
        root.mx = Math.max(left.mx, right.mx);
        root.lmx = left.lmx;
        root.rmx = right.rmx;
        const a = left.r - left.l + 1;
        const b = right.r - right.l + 1;
        if (this.s[left.r - 1] === this.s[right.l - 1]) {
            if (left.lmx === a) {
                root.lmx += right.lmx;
            }
            if (right.rmx === b) {
                root.rmx += left.rmx;
            }
            root.mx = Math.max(root.mx, left.rmx + right.lmx);
        }
    }
}

function longestRepeating(s: string, queryCharacters: string, queryIndices: number[]): number[] {
    const tree = new SegmentTree(s);
    const k = queryIndices.length;
    const ans: number[] = new Array(k);
    const n = s.length;
    for (let i = 0; i < k; ++i) {
        const x = queryIndices[i] + 1;
        const v = queryCharacters[i];
        tree.modify(1, x, v);
        ans[i] = tree.query(1, 1, n);
    }
    return ans;
}
type Node struct {
	l, r         int
	lmx, rmx, mx int
}

type SegmentTree struct {
	s  []byte
	tr []*Node
}

func NewNode(l, r int) *Node {
	return &Node{l: l, r: r, lmx: 1, rmx: 1, mx: 1}
}

func NewSegmentTree(s string) *SegmentTree {
	n := len(s)
	tree := &SegmentTree{s: []byte(s), tr: make([]*Node, n<<2)}
	tree.build(1, 1, n)
	return tree
}

func (tree *SegmentTree) build(u, l, r int) {
	tree.tr[u] = NewNode(l, r)
	if l == r {
		return
	}
	mid := (l + r) >> 1
	tree.build(u<<1, l, mid)
	tree.build(u<<1|1, mid+1, r)
	tree.pushup(u)
}

func (tree *SegmentTree) modify(u, x int, v byte) {
	if tree.tr[u].l == x && tree.tr[u].r == x {
		tree.s[x-1] = v
		return
	}
	mid := (tree.tr[u].l + tree.tr[u].r) >> 1
	if x <= mid {
		tree.modify(u<<1, x, v)
	} else {
		tree.modify(u<<1|1, x, v)
	}
	tree.pushup(u)
}

func (tree *SegmentTree) query(u, l, r int) int {
	if tree.tr[u].l >= l && tree.tr[u].r <= r {
		return tree.tr[u].mx
	}
	mid := (tree.tr[u].l + tree.tr[u].r) >> 1
	ans := 0
	if r <= mid {
		ans = tree.query(u<<1, l, r)
	} else if l > mid {
		ans = max(ans, tree.query(u<<1|1, l, r))
	} else {
		ans = max(tree.query(u<<1, l, r), tree.query(u<<1|1, l, r))
	}
	return ans
}

func (tree *SegmentTree) pushup(u int) {
	root := tree.tr[u]
	left := tree.tr[u<<1]
	right := tree.tr[u<<1|1]
	root.mx = max(left.mx, right.mx)
	root.lmx = left.lmx
	root.rmx = right.rmx
	a := left.r - left.l + 1
	b := right.r - right.l + 1
	if tree.s[left.r-1] == tree.s[right.l-1] {
		if left.lmx == a {
			root.lmx += right.lmx
		}
		if right.rmx == b {
			root.rmx += left.rmx
		}
		root.mx = max(root.mx, left.rmx+right.lmx)
	}
}

func longestRepeating(s string, queryCharacters string, queryIndices []int) (ans []int) {
	tree := NewSegmentTree(s)
	n := len(s)
	for i, v := range queryCharacters {
		x := queryIndices[i] + 1
		tree.modify(1, x, byte(v))
		ans = append(ans, tree.query(1, 1, n))
	}
	return
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Naive Approach with Recalculation

Time Complexity: O(k * n), iterating over the string for each query.
Space Complexity: O(1) for additional data structures, beyond space for result storage.

Optimized Sliding Window Approach

Time Complexity: O(k * m), m being fixed to targeted local regions per update.
Space Complexity: O(1) outside the output holding structure.

Segment Tree–

Complexity analysis

ApproachTimeSpaceWhen to Use
Naive RecalculationO(n) per queryO(1)Good for understanding the problem or when the number of updates is small
Sliding Window Style Linear ScanO(n) per queryO(1)Cleaner linear pass that tracks consecutive runs without evaluating substrings
Segment Tree OptimizationO(log n) per updateO(n)Best for large inputs with many updates where recomputation becomes too slow

Frequently asked questions

Is Longest Substring of One Repeating Character easy or hard?

The problem is classified as Hard because it combines dynamic updates with substring queries. The naive solution is straightforward, but designing an efficient O(log n) update strategy using a segment tree requires strong understanding of range data structures.

Longest Substring of One Repeating Character Python/Java solution

Python and Java implementations typically either scan the string after each update or implement a segment tree to maintain segment information. The segment tree version provides O(log n) updates, while the simpler scan approach runs in O(n) per query.

How to solve Longest Substring of One Repeating Character in O(n)?

Process the string with a single linear scan that tracks consecutive runs of identical characters. Maintain a counter for the current run and update a maximum length variable whenever the run grows. After each update to the string, repeat the scan to compute the longest repeating substring in O(n) time.

What is the best approach for Longest Substring of One Repeating Character?

The most efficient solution uses a segment tree that stores the longest repeating substring length for each segment along with prefix and suffix run lengths. Each character update modifies a single leaf and recalculates parent nodes in O(log n) time. This allows the longest repeating substring to be retrieved after every query efficiently.

Is Longest Substring of One Repeating Character asked at Google/Amazon/Meta?

Problems involving dynamic string updates and longest repeating segments appear in interviews at companies like Google, Amazon, and Meta. They are commonly used to evaluate knowledge of segment trees, interval merging, and efficient update/query data structures.

What data structure is used in Longest Substring of One Repeating Character?

The optimal solution uses a segment tree. Each node stores the maximum repeating substring length inside the segment along with prefix and suffix run lengths, allowing fast recomputation when a character changes.

What is the time complexity of Longest Substring of One Repeating Character?

A simple recalculation approach scans the string after every update, giving O(n) time per query and O(n * q) overall for q updates. A segment tree optimization reduces update time to O(log n) while maintaining the longest repeating substring in each node.

Comments

Now write it yourselfClose this page and solve Longest Substring of One Repeating Character in the editor, without looking.
Practise Longest Substring of One Repeating Character