📌  相关文章
📜  具有至少 K 个具有相同频率的成对不同字符的子串计数(1)

📅  最后修改于: 2023-12-03 15:22:35.619000             🧑  作者: Mango

题目概述

该题目要求我们统计给定字符串中,具有至少 K 个具有相同频率的成对不同字符的子串数量。一些例子如下:

  • 输入: "AABABBA", K=2,输出:4
  • 输入: "AABCAAAB", K=3,输出:0
  • 输入: "ABCDE", K=1,输出:5

其中,第一个例子中有4个子串满足要求,它们分别是 "AA"、"AB"、"BB"、"BA";第二个例子中没有符合要求的子串;而第三个例子中任何两个字符出现次数都是不同的,因此任意两个不同字符组成的子串都符合要求。

解题思路

首先,注意到字符串的长度最多为 $10^5$,因此朴素的做法显然会超时。为了解决这个问题,我们需要想到某些算法技巧来优化。

具体来说,我们可以观察到任何符合条件的子串一定由若干个长度为 $2K$ 的区间组成,且每个区间中每个字符的个数都相等。例如,在第一个例子中,"AA"、"AB"、"BB"、"BA"分别对应于 "AA+BA"、 "AB+BA" 、 "BA+BB"、 "BA+AB" 两个区间。在第三个例子中,任意两个不同字符都可以当做一个区间来看。

我们考虑对于每个可能的区间,计算其中所有字符的出现次数并记录下来。这可以通过一个类似于滑动窗口的方法来实现,时间复杂度为 $\mathcal{O}(n, |\Sigma|)$,其中 $|\Sigma|$ 是字符集大小。接下来,我们可以使用哈希表来记录这些区间中每种不同字符的出现次数,得到一个形如 $\mathrm{freq}(i,c)$ 的函数。

接下来,我们遍历所有可能的字符对 $(c_1,c_2)$ 并统计有多少个区间 $\mathrm{cnt}$ 满足 $\mathrm{freq}(i,c_1)=\mathrm{freq}(i,c_2)=K$。顺带一提,其实这相当于计算每个字符对 $(c_1,c_2)$ 对答案的贡献,再将所有贡献相加即可。因此,这里使用哈希表来记录每个字符对对答案的贡献即可。

最后,我们统计所有贡献的和并输出即可。时间复杂度仍为 $\mathcal{O}(n, |\Sigma|)$。

详细实现

下面给出详细的实现过程。

求解子串出现次数

首先,我们需要为每个可能的区间计算其中所有字符的出现次数,并将结果存储到哈希表中。这可以通过一个类似于滑动窗口的方法来实现。具体来说,维护两个指针 $l,r$,表示当前区间对应的下标范围为 $[l,r]$,并记录其中每种字符出现的次数。每次将 $r$ 向右移动一位,同时将对应字符的出现次数加1,并检查新的区间中所包含的字符是否符合要求。

最终,我们将每个区间中不同字符的出现次数打包成一个字符串,以该字符串为键将该区间出现的次数加入到哈希表中。

计算字符对的贡献

接下来,我们需要统计每个字符对 $(c_1,c_2)$ 对答案的贡献。具体来说,我们遍历所有可能的字符对,并统计有多少个区间 $\mathrm{cnt}$ 满足 $\mathrm{freq}(i,c_1)=\mathrm{freq}(i,c_2)=K$。顺带一提,其实这相当于计算所有区间对 $(c_1,c_2)$ 的贡献,再将所有贡献相加即可。

为了实现这个统计过程,我们可以再次遍历所有区间,并在哈希表中查找 $(c_1,c_2)$ 出现的次数并将其累加。例如,我们可以使用一个哈希表 $G$,以形如 $"c1c2"$ 的字符串为键记录对应的出现次数。遍历每个区间 $s$,将 $s$ 中所有字符对 $(c_1,c_2)$ 出现的次数累加到 $G["c1c2"]$ 中。这里需要注意,如果 $c_1=c_2$,则不需要将其纳入统计范围。

计算答案

最后,我们将所有字符对的贡献相加即可得到最终的答案。

代码实现

下面给出参考代码,其中 $K$ 在代码中为 $k$。