计算中位数与字符串的第 K 个字符相同的奇数长度子字符串
在此问题中,我们将计算给定字符串中包含所有偶数频率字符或任何奇数频率单个字符的子字符串的数量。
我们将使用位掩码技术来解决问题。在位掩码中,二进制字符串的每个位代表字符。
问题陈述 - 我们给出了一个长度为 N 的字符串 alpha。还给出了 'a' <= alpha[i] <= 't'。我们需要计算所有字符都是偶数频率的子字符串的数量,或者只有一个字符是奇数频率而其他字符是偶数频率的子字符串的数量。
示例
输入
alpha = "pqq";
输出
5
说明- 有效子字符串为 pqq、p、q、q 和 qq。
输入
alpha = "mnbn";
输出
5
解释- 有效子字符串为 nbn、m、n、b 和 n。
方法 1
此方法使用位掩码来计算包含所有偶数频率字符或仅包含一个奇数频率字符的子字符串的数量。
逻辑 - 当我们对两个相同的整数进行异或时,结果为 0。
因此,我们将遍历字符串,并对每个字符值与初始位掩码值进行异或。如果之前出现过相同的位掩码,我们可以说子字符串包含所有具有偶数频率的字符,因为掩码的差为 0。此外,我们将添加和删除每个字符,以计算包含具有奇数频率的单个字符的子字符串。
算法
步骤 1 - 初始化大小为 220 的矩阵列表。
步骤 2 - 用 0 初始化"bitMask",表示初始掩码,用 0 初始化"cnt",以存储有效子字符串的数量。
步骤 3 - 用 1 初始化矩阵[0],因为空字符串始终有效。
步骤 4 - 开始遍历字符串。
步骤 5 - 将 1 按字符值左移,并将其与位掩码值进行异或。这意味着我们将当前字符添加到掩码中。
步骤 6 - 将矩阵列表中相同位掩码的数量添加到"cnt"。例如,在"acbbe"字符串中,第 1 个和第 3 个索引处的位掩码变为相同。因此,我们可以取"bb"子字符串。
步骤 7 - 使用循环进行 0 到 20 次迭代。在每次迭代中,将字符左移 1 个 p,并将其与位掩码进行异或以从子字符串中删除该字符。再次将之前出现过的相同掩码的数量添加到"cnt"变量中。
步骤 8 - 增加列表中当前位掩码的值。
步骤 9 - 返回"cnt"值。
示例
#include <bits/stdc++.h> using namespace std; int validSubStrs(string &alpha, int K) { int len = alpha.size(); int cnt = 0; // 获取应包含第 K 个字符的所有子字符串 for (int p = 0; p < K; p++) { for (int q = K - 1; q < len; q++) { string temp = alpha.substr(p, q - p + 1); // 如果临时字符串的大小是奇数 if (temp.size() % 2 != 0) { // 按升序对字符串进行排序 sort(temp.begin(), temp.end()); // 检查字符串的中位数 if(temp[(temp.size() - 1) / 2] == alpha[K - 1]) cnt++; } } } return cnt; } int main() { string alpha = "acdb"; int K = 2; cout << "包含第 K 个字符作为中位数的子字符串的数量为 " << validSubStrs(alpha, K); return 0; }
输出
根据问题陈述,子字符串的总数为 5
时间复杂度 - 遍历字符串的 O(N)。
空间复杂度 - O(2M),其中 M 是字符串中的唯一字符。
程序员可以通过获取每个子字符串并根据问题陈述检查子字符串是否有效来解决问题。但是,位掩码是解决此类问题的最佳技术。