2023-06-15 LeetCode每日一题(构建回文串检测)

2023-06-15每日一题

一、题目编号

1177. 构建回文串检测

二、题目链接

点击跳转到题目位置

三、题目描述

给你一个字符串 s,请你对 s 的子串进行检测。

每次检测,待检子串都可以表示为 queries[i] = [left, right, k]。我们可以 重新排列 子串 s[left], …, s[right],并从中选择 最多 k 项替换成任何小写英文字母。

如果在上述检测过程中,子串可以变成回文形式的字符串,那么检测结果为 true,否则结果为 false。

返回答案数组 answer[],其中 answer[i] 是第 i 个待检子串 queries[i] 的检测结果。

注意:在替换时,子串中的每个字母都必须作为 独立的 项进行计数,也就是说,如果 s[left…right] = “aaa” 且 k = 2,我们只能替换其中的两个字母。(另外,任何检测都不会修改原始字符串 s,可以认为每次检测都是独立的)

提示:

  • 1 <= s.length, queries.length <= 105
  • 0 <= queries[i][0] <= queries[i][1] < s.length
  • 0 <= queries[i][2] <= s.length
  • s 中只有小写英文字母

四、解题代码

class Solution {
public:
    vector<bool> canMakePaliQueries(string s, vector<vector<int>>& queries) {
        int n = s.size();
        int count[n+10];
        memset(count, 0, sizeof(count));
        for(int i = 0; i < n; ++i){
            count[i+1] = count[i] ^ (1 << (s[i] - 'a'));
        }
        vector<bool> res;
        int m = queries.size();
        for(int i = 0; i < m; ++i){
            int left = queries[i][0];
            int right = queries[i][1];
            int k = queries[i][2];
            int x = count[right+1] ^ count[left];
            int bits = 0;
            while(x > 0){
                x &= (x-1);
                bits++;
            }
            if(bits <= 2 * k + 1){
                res.push_back(true);
            } else{
                res.push_back(false);
            }
        }
    return res;
    }
};

五、解题思路

(1) 首先先用26位数字来代表26个字母,1 << 0表示a。

(2) 统计前缀字符串数组。

(3) count[i]表示下标0 ~ i-1的字符串是多少。

(4) 用count[right + 1] ^ count[left]来表示left ~ right之间的字符串,然后统计奇数的字符数目。偶数的放两边自然可以形成回文串,那么奇数的该如何处理呢。假设为bits个,那么允许修改k个。一个修改可以影响两个,那么k个的上限是将2 * k + 1长度的字符串转化为回文串,那么由此可见,只要bits <= 2 * k + 1即可。

你可能感兴趣的:(LeetCode每日一题,leetcode,算法,数据结构)