You are given a 0-indexed string s having an even length n.
You are also given a 0-indexed 2D integer array, queries, where
queries[i] = [ai, bi, ci, di].
For each query i, you are allowed to perform the following operations:
Rearrange the characters within the substrings[ai:bi], where 0 <= ai <= bi < n / 2.
Rearrange the characters within the substrings[ci:di], where n / 2 <= ci <= di < n.
For each query, your task is to determine whether it is possible to make s a
palindrome by performing the operations.
Each query is answered independently of the others.
Return _a0-indexed array _answer, whereanswer[i] == trueif it is possible to makesa palindrome by performing operations specified by theithquery, andfalseotherwise.
A substring is a contiguous sequence of characters within a string.
s[x:y] represents the substring consisting of characters from the index x to index y in s, both inclusive.
Input: s ="abcabc", queries =[[1,1,3,5],[0,2,5,5]]Output: [true,true]Explanation: In this example, there are two queries:In the first query:- a0 =1, b0 =1, c0 =3, d0 =5.- So, you are allowed to rearrange s[1:1]=> a _b_ cabc and s[3:5]=> abc _abc_.- To make s a palindrome, s[3:5] can be rearranged to become => abc _cba_.- Now, s is a palindrome. So, answer[0]=true.In the second query:- a1 =0, b1 =2, c1 =5, d1 =5.- So, you are allowed to rearrange s[0:2]=> _abc_ abc and s[5:5]=> abcab _c_.- To make s a palindrome, s[0:2] can be rearranged to become => _cba_ abc.- Now, s is a palindrome. So, answer[1]=true.
Input: s ="abbcdecbba", queries =[[0,2,7,9]]Output: [false]Explanation: In this example, there is only one query.a0 =0, b0 =2, c0 =7, d0 =9.So, you are allowed to rearrange s[0:2]=> _abb_ cdecbba and s[7:9]=> abbcdec _bba_.It is not possible to make s a palindrome by rearranging these substrings because s[3:6]is not a palindrome.So, answer[0]=false.
Input: s ="acbcab", queries =[[1,2,4,5]]Output: [true]Explanation: In this example, there is only one query.a0 =1, b0 =2, c0 =4, d0 =5.So, you are allowed to rearrange s[1:2]=> a _cb_ cab and s[4:5]=> acbc _ab_.To make s a palindrome s[1:2] can be rearranged to become a _bc_ cab.Then, s[4:5] can be rearranged to become abcc _ba_.Now, s is a palindrome. So, answer[0]=true.
To make the string a palindrome by rearranging two substrings, the first half and the reversed second half must have the same character counts after rearrangement. We can use prefix sums to quickly compute character frequencies for any substring, and for each query, check if the two halves can be rearranged to match.
classSolution {
public: vector<bool> canMakePalindromeQueries(string s, vector<vector<int>>& queries) {
int n = s.size(), m = n/2;
vector<vector<int>> preL(m+1, vector<int>(26)), preR(m+1, vector<int>(26));
for (int i =0; i < m; ++i) {
preL[i+1] = preL[i];
preL[i+1][s[i]-'a']++;
}
for (int i = m; i < n; ++i) {
preR[i-m+1] = preR[i-m];
preR[i-m+1][s[i]-'a']++;
}
vector<bool> ans;
for (auto& q : queries) {
int a=q[0], b=q[1], c=q[2]-m, d=q[3]-m;
bool ok = true;
for (int i =0; i < a; ++i) {
if (s[i] != s[n-1-i]) { ok = false; break; }
}
for (int i = b+1; i < m; ++i) {
if (s[i] != s[n-1-i]) { ok = false; break; }
}
for (int i =0; i < c; ++i) {
if (s[m+i] != s[m-1-i]) { ok = false; break; }
}
for (int i = d+1; i < m; ++i) {
if (s[m+i] != s[m-1-i]) { ok = false; break; }
}
if (!ok) { ans.push_back(false); continue; }
vector<int> left(26), right(26);
for (int j =0; j <26; ++j) {
left[j] = preL[b+1][j] - preL[a][j];
right[j] = preR[d+1][j] - preR[c][j];
}
sort(left.begin(), left.end());
sort(right.begin(), right.end());
ans.push_back(left == right);
}
return ans;
}
};
classSolution {
public List<Boolean>canMakePalindromeQueries(String s, int[][] queries) {
int n = s.length(), m = n/2;
int[][] preL =newint[m+1][26], preR =newint[m+1][26];
for (int i = 0; i < m; i++) {
System.arraycopy(preL[i], 0, preL[i+1], 0, 26);
preL[i+1][s.charAt(i)-'a']++;
}
for (int i = m; i < n; i++) {
System.arraycopy(preR[i-m], 0, preR[i-m+1], 0, 26);
preR[i-m+1][s.charAt(i)-'a']++;
}
List<Boolean> ans =new ArrayList<>();
for (int[] q : queries) {
int a=q[0], b=q[1], c=q[2]-m, d=q[3]-m;
boolean ok =true;
for (int i = 0; i < a; i++) if (s.charAt(i) != s.charAt(n-1-i)) { ok =false; break; }
for (int i = b+1; i < m; i++) if (s.charAt(i) != s.charAt(n-1-i)) { ok =false; break; }
for (int i = 0; i < c; i++) if (s.charAt(m+i) != s.charAt(m-1-i)) { ok =false; break; }
for (int i = d+1; i < m; i++) if (s.charAt(m+i) != s.charAt(m-1-i)) { ok =false; break; }
if (!ok) { ans.add(false); continue; }
int[] left =newint[26], right =newint[26];
for (int j = 0; j < 26; j++) {
left[j]= preL[b+1][j]- preL[a][j];
right[j]= preR[d+1][j]- preR[c][j];
}
Arrays.sort(left);
Arrays.sort(right);
ans.add(Arrays.equals(left, right));
}
return ans;
}
}
classSolution {
funcanMakePalindromeQueries(s: String, queries: Array<IntArray>): List<Boolean> {
val n = s.length; val m = n/2val preL = Array(m+1) { IntArray(26) }
val preR = Array(m+1) { IntArray(26) }
for (i in0 until m) {
for (j in0..25) preL[i+1][j] = preL[i][j]
preL[i+1][s[i]-'a']++ }
for (i in m until n) {
for (j in0..25) preR[i-m+1][j] = preR[i-m][j]
preR[i-m+1][s[i]-'a']++ }
val ans = mutableListOf<Boolean>()
for (q in queries) {
val(a, b, c0, d0) = q
val c = c0-m; val d = d0-m
var ok = truefor (i in0 until a) if (s[i] != s[n-1-i]) { ok = false; break }
for (i in b+1 until m) if (s[i] != s[n-1-i]) { ok = false; break }
for (i in0 until c) if (s[m+i] != s[m-1-i]) { ok = false; break }
for (i in d+1 until m) if (s[m+i] != s[m-1-i]) { ok = false; break }
if (!ok) { ans.add(false); continue }
val left = IntArray(26) { preL[b+1][it] - preL[a][it] }
val right = IntArray(26) { preR[d+1][it] - preR[c][it] }
left.sort(); right.sort()
ans.add(left.contentEquals(right))
}
return ans
}
}
classSolution:
defcanMakePalindromeQueries(self, s: str, queries: list[list[int]]) -> list[bool]:
n, m = len(s), len(s)//2 preL = [[0]*26for _ in range(m+1)]
preR = [[0]*26for _ in range(m+1)]
for i in range(m):
for j in range(26):
preL[i+1][j] = preL[i][j]
preL[i+1][ord(s[i])-97] +=1for i in range(m, n):
for j in range(26):
preR[i-m+1][j] = preR[i-m][j]
preR[i-m+1][ord(s[i])-97] +=1 ans = []
for a, b, c0, d0 in queries:
c, d = c0-m, d0-m
ok =Truefor i in range(a):
if s[i] != s[n-1-i]: ok =False; breakfor i in range(b+1, m):
if s[i] != s[n-1-i]: ok =False; breakfor i in range(c):
if s[m+i] != s[m-1-i]: ok =False; breakfor i in range(d+1, m):
if s[m+i] != s[m-1-i]: ok =False; breakifnot ok: ans.append(False); continue left = [preL[b+1][j] - preL[a][j] for j in range(26)]
right = [preR[d+1][j] - preR[c][j] for j in range(26)]
ans.append(sorted(left) == sorted(right))
return ans
impl Solution {
pubfncan_make_palindrome_queries(s: String, queries: Vec<Vec<i32>>) -> Vec<bool> {
let n = s.len();
let m = n/2;
let s = s.as_bytes();
letmut pre_l =vec![vec![0; 26]; m+1];
letmut pre_r =vec![vec![0; 26]; m+1];
for i in0..m {
pre_l[i+1].clone_from(&pre_l[i]);
pre_l[i+1][(s[i]-b'a') asusize] +=1;
}
for i in m..n {
pre_r[i-m+1].clone_from(&pre_r[i-m]);
pre_r[i-m+1][(s[i]-b'a') asusize] +=1;
}
letmut ans =vec![];
for q in queries {
let (a, b, c, d) = (q[0] asusize, q[1] asusize, q[2] asusize- m, q[3] asusize- m);
letmut ok =true;
for i in0..a { if s[i] != s[n-1-i] { ok =false; break; } }
for i in b+1..m { if s[i] != s[n-1-i] { ok =false; break; } }
for i in0..c { if s[m+i] != s[m-1-i] { ok =false; break; } }
for i in d+1..m { if s[m+i] != s[m-1-i] { ok =false; break; } }
if!ok { ans.push(false); continue; }
letmut left =vec![0; 26];
letmut right =vec![0; 26];
for j in0..26 {
left[j] = pre_l[b+1][j] - pre_l[a][j];
right[j] = pre_r[d+1][j] - pre_r[c][j];
}
left.sort(); right.sort();
ans.push(left == right);
}
ans
}
}
⏰ Time complexity: O(n + q*26), where n is the length of s and q is the number of queries. Preprocessing is O(n), each query is O(26 log 26) for sorting and O(m) for checking fixed positions.
🧺 Space complexity: O(n), for the prefix sum arrays.