Loading problems...
TL;DR: Use a variable-size sliding window to group contiguous identical characters, calculate the frequency of all special substrings derived from these groups, and return the maximum length occurring at least three times.
In LeetCode 2981, "Find Longest Special Substring That Occurs Thrice I", you are given a string s. You must identify the length of the longest substring that meets two criteria:
If no such substring exists, return -1. While the constraints for this specific version (I) are small (), the logic required is foundational for handling larger string constraints efficiently.
The naive approach involves generating every possible substring, checking if it is "special," and then counting its total occurrences.
s using nested loops.Pseudo-code:
textmax_len = -1 for i from 0 to n: for j from i to n: sub = s[i...j] if isSpecial(sub): map[sub]++ for sub, count in map: if count >= 3: max_len = max(max_len, sub.length)
Time Complexity: . Generating substrings is , and verifying/hashing each can take . Why it fails: While allows this to pass, this approach scales poorly. For larger constraints (like version II of this problem), results in Time Limit Exceeded (TLE). It performs redundant checks on parts of the string that have already been processed.
The key intuition is that we do not need to check arbitrary substrings like index 2 to 5. We only care about contiguous blocks of identical characters.
If we find a block like "aaaa" (length 4), this single block implicitly contains:
"aaaa")"aaa")"aa")"a")Invariant:
The sliding window [left, right) always maintains a range of identical characters.
Visual Description:
Imagine the window starting at the first character. The right pointer expands as long as s[right] matches s[left]. When s[right] differs, the window [left, right) represents a maximal special substring. We process this block to update our counts, then the left pointer jumps to right to begin a new window. This ensures we process the string in a single linear pass (plus a small inner loop for counting), drastically reducing complexity compared to brute force.

Let's trace s = "aaaba":
left = 0, counts map empty.right = 0: s[0] is 'a'. Continue.right = 1: s[1] is 'a' (matches s[left]). Continue.right = 2: s[2] is 'a' (matches s[left]). Continue.right = 3: s[3] is 'b' (mismatch!).
[0, 3) is "aaa". Length . Char 'a'.left = 3.right = 4: s[4] is 'a' (mismatch with s[left] which is 'b').
[3, 4) is "b". Length . Char 'b'.left=4.
[4, 5) is "a". Length . Char 'a'.The algorithm correctly identifies every maximal contiguous segment of identical characters. Since any "special" substring must be part of such a segment, processing these segments covers all possibilities. The formula mathematically accounts for every valid position a substring of length could occupy within a block of length . By aggregating these counts globally, we ensure that split occurrences (e.g., "aa...aa") are summed correctly.
cpp#include <vector> #include <string> #include <algorithm> #include <map> using namespace std; class Solution { public: int maximumLength(string s) { int n = s.length(); // count[char_index][length] stores frequency vector<vector<int>> count(26, vector<int>(n + 1, 0)); int left = 0; for (int right = 0; right < n; ++right) { // Check if window breaks (next char differs) or we are at the end if (right == n - 1 || s[right] != s[right + 1]) { int len = right - left + 1; int charIdx = s[left] - 'a'; // A block of length 'len' contributes to all sub-lengths for (int k = 1; k <= len; ++k) { count[charIdx][k] += (len - k + 1); } // Move left to the start of the next block left = right + 1; } } int maxLen = -1; // Check all characters and lengths for (int i = 0; i < 26; ++i) { for (int len = n; len >= 1; --len) { if (count[i][len] >= 3) { maxLen = max(maxLen, len); break; // Optimization: found longest for this char } } } return maxLen; } };
javaclass Solution { public int maximumLength(String s) { int n = s.length(); // count[char_index][length] int[][] count = new int[26][n + 1]; int left = 0; for (int right = 0; right < n; right++) { // Detect end of a contiguous block if (right == n - 1 || s.charAt(right) != s.charAt(right + 1)) { int len = right - left + 1; int charIdx = s.charAt(left) - 'a'; // Update frequencies for all valid sub-lengths within this block for (int k = 1; k <= len; k++) { count[charIdx][k] += (len - k + 1); } // Reset window start left = right + 1; } } int maxLen = -1; for (int i = 0; i < 26; i++) { for (int len = n; len >= 1; len--) { if (count[i][len] >= 3) { maxLen = Math.max(maxLen, len); break; // Found max for this char } } } return maxLen; } }
pythonclass Solution: def maximumLength(self, s: str) -> int: n = len(s) # Dictionary to map (char, length) -> frequency counts = {} left = 0 for right in range(n): # If current char is last char or next char is different if right == n - 1 or s[right] != s[right + 1]: length = right - left + 1 char = s[left] # Update counts for all possible sub-lengths for k in range(1, length + 1): key = (char, k) # Formula: a block of length L has (L - k + 1) substrings of length k counts[key] = counts.get(key, 0) + (length - k + 1) left = right + 1 max_len = -1 for (char, length), count in counts.items(): if count >= 3: max_len = max(max_len, length) return max_len
The Sliding Window - Variable Size pattern is versatile and appears in many popular interview questions:
Why does my solution fail on "aaaa"?
count += (L - k + 1).Why do I get an Index Out of Bounds error?
s[right+1] without checking if first.left = 4.right == n - 1right == n - 1 || s[right] != s[right+1].Why is my result -1 even when there is a valid answer?
max_len to 0 or forgetting to handle the case where the longest special substring has length 1.max_len = -1. Ensure your loop checks lengths starting from 1.