Substring XOR Queries
MedPrompt
You are given a binary string s, and a 2D integer array queries where queries[i] = [firsti, secondi].
For the ith query, find the shortest substring of s whose decimal value, val, yields secondi when bitwise XORed with firsti. In other words, val ^ firsti == secondi.
The answer to the ith query is the endpoints (0-indexed) of the substring [lefti, righti] or [-1, -1] if no such substring exists. If there are multiple answers, choose the one with the minimum lefti.
Return an array ans where ans[i] = [lefti, righti] is the answer to the ith query.
A substring is a contiguous non-empty sequence of characters within a string.
Example 1:
[0,2]Example 2:
[-1,-1] is returnedExample 3:
[0,0]
Constraints:
1 <= s.length <= 104s[i]is either'0'or'1'.1 <= queries.length <= 1050 <= firsti, secondi <= 109
Approaches
3 approaches with complexity analysis and trade-offs.
The most straightforward approach is to process each query independently. For every query, we calculate the required decimal value, val, by XORing first and second. Then, we iterate through all possible substrings of the input string s, convert each substring from its binary representation to a decimal value, and check if it matches the required val. To ensure we find the shortest substring with the minimum left index, we can structure our search by first iterating through substring lengths (from 1 to s.length()) and then through their starting positions (from left to right). The first match we find will be the optimal one for that query.
Algorithm
- For each query
[first, second]:- Calculate the target value:
target = first ^ second. - Initialize a flag
found = falseand a result arrayans_i = [-1, -1]. - Iterate through possible substring lengths
lenfrom 1 to the length ofs. - For each
len, iterate through all possible starting indicesifrom 0 tos.length() - len. - Extract the substring
sub = s.substring(i, i + len). - Convert
subto its decimal valueval. Be mindful of potentialNumberFormatExceptionfor long substrings, although we only need to consider lengths up to about 31. - If
valequalstarget, we have found the shortest substring with the minimum left index due to the loop order. Setans_i = [i, i + len - 1], setfound = true, and break from all loops for the current query. - If
foundis true, stop searching for the current query.
- Calculate the target value:
- After checking all possibilities for a query, if no match was found, the answer remains
[-1, -1]. - Collect the answers for all queries and return them.
Walkthrough
This brute-force method directly translates the problem statement into a solution. For each of the Q queries, we determine the target decimal value. The core of the algorithm is a nested loop structure that generates all substrings of s. To meet the problem's criteria for the 'best' substring (shortest, then smallest starting index), we iterate on length len from 1 upwards. For a fixed len, we iterate on the starting position i from 0 upwards. This ensures that the first time we find a substring whose decimal value matches our target, it is guaranteed to be one of the shortest possible length, and among those, the one with the minimum starting index.
class Solution { public int[][] substringXorQueries(String s, int[][] queries) { int q = queries.length; int n = s.length(); int[][] ans = new int[q][2]; for (int k = 0; k < q; k++) { int first = queries[k][0]; int second = queries[k][1]; int target = first ^ second; int[] currentAns = {-1, -1}; int minLength = Integer.MAX_VALUE; // Iterate through all substrings for (int i = 0; i < n; i++) { long currentVal = 0; for (int j = i; j < n; j++) { // Optimization: limit substring length to avoid overflow and unnecessary work if (j - i + 1 > 32) break; currentVal = (currentVal << 1) | (s.charAt(j) - '0'); if (currentVal == target) { int currentLength = j - i + 1; if (currentLength < minLength) { minLength = currentLength; currentAns[0] = i; currentAns[1] = j; } // The problem asks for min left for the same length. // A better loop structure is needed to avoid this check. // Iterating by length first is better. } } } ans[k] = currentAns; } // The above code finds shortest, but not necessarily min-left first. // A correct brute-force would be: for (int k = 0; k < q; k++) { int target = queries[k][0] ^ queries[k][1]; ans[k] = new int[]{-1, -1}; boolean found = false; for (int len = 1; len <= n; len++) { if (len > 32) break; // Optimization for (int i = 0; i <= n - len; i++) { int j = i + len - 1; String sub = s.substring(i, j + 1); try { int val = Integer.parseInt(sub, 2); if (val == target) { ans[k][0] = i; ans[k][1] = j; found = true; break; } } catch (NumberFormatException e) { /* Value too large */ } } if (found) break; } } return ans; }}Complexity
Time
O(Q * N * L), where Q is the number of queries, N is the length of `s`, and L is the maximum length of a relevant substring (approx. 31). For each query, we iterate through O(N * L) substrings, and converting each to an integer takes O(L). This results in a total time complexity that is too high for the given constraints.
Space
O(1) or O(Q) if we consider the space for the output array, where Q is the number of queries.
Trade-offs
Pros
Simple to conceptualize and implement.
Requires minimal extra space, only for storing the final answer.
Cons
Extremely inefficient and will not pass the time limits for the given constraints.
Repeatedly performs the same substring conversions across different queries.
Solutions
Solution
class Solution {public int[][] substringXorQueries(String s, int[][] queries) { Map<Integer, int[]> d = new HashMap<>(); int n = s.length(); for (int i = 0; i < n; ++i) { int x = 0; for (int j = 0; j < 32 && i + j < n; ++j) { x = x << 1 | (s.charAt(i + j) - '0'); d.putIfAbsent(x, new int[]{i, i + j}); if (x == 0) { break; } } } int m = queries.length; int[][] ans = new int[m][2]; for (int i = 0; i < m; ++i) { int first = queries[i][0], second = queries[i][1]; int val = first ^ second; ans[i] = d.getOrDefault(val, new int[]{-1, -1}); } return ans; }}Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.