Can Make Palindrome from Substring

medium prefix sum parity palindrome

Problem

Given a string s and queries [left, right, k]. For each query, take the substring s[left..right]. You may rearrange its letters freely and may replace up to k of them with any letters. Return true if the substring can be turned into a palindrome. A palindrome can be formed when at most one character has an odd count, so each replacement can fix one odd-count character; the answer is (number of odd-count characters) / 2 ≤ k.

Inputs = "abcda", query = [0, 4, 1]
Outputtrue
Substring "abcda" has odd counts for b, c, d (3 odds). We need floor(3/2)=1 replacement, and k=1, so it works.

def can_make_pali_queries(s, queries):
    n = len(s)
    pre = [0] * (n + 1)
    for i, ch in enumerate(s):
        pre[i + 1] = pre[i] ^ (1 << (ord(ch) - 97))
    res = []
    for left, right, k in queries:
        mask = pre[right + 1] ^ pre[left]
        odds = bin(mask).count("1")
        res.append(odds // 2 <= k)
    return res
function canMakePaliQueries(s, queries) {
  const n = s.length;
  const pre = new Array(n + 1).fill(0);
  for (let i = 0; i < n; i++) {
    pre[i + 1] = pre[i] ^ (1 << (s.charCodeAt(i) - 97));
  }
  return queries.map(function ([left, right, k]) {
    let mask = pre[right + 1] ^ pre[left];
    let odds = 0;
    while (mask) { odds += mask & 1; mask >>= 1; }
    return Math.floor(odds / 2) <= k;
  });
}
class Solution {
    public List<Boolean> canMakePaliQueries(String s, int[][] queries) {
        int n = s.length();
        int[] pre = new int[n + 1];
        for (int i = 0; i < n; i++) {
            pre[i + 1] = pre[i] ^ (1 << (s.charAt(i) - 'a'));
        }
        List<Boolean> res = new ArrayList<>();
        for (int[] q : queries) {
            int mask = pre[q[1] + 1] ^ pre[q[0]];
            int odds = Integer.bitCount(mask);
            res.add(odds / 2 <= q[2]);
        }
        return res;
    }
}
vector<bool> canMakePaliQueries(string s, vector<vector<int>>& queries) {
    int n = s.size();
    vector<int> pre(n + 1, 0);
    for (int i = 0; i < n; i++) {
        pre[i + 1] = pre[i] ^ (1 << (s[i] - 'a'));
    }
    vector<bool> res;
    for (auto& q : queries) {
        int mask = pre[q[1] + 1] ^ pre[q[0]];
        int odds = __builtin_popcount(mask);
        res.push_back(odds / 2 <= q[2]);
    }
    return res;
}
Time: O(n + q) Space: O(n)