题目描述(难度中等)
给你一个字符串 s ,请你返回满足以下条件且出现次数最大的任意子串的出现次数:
- 子串中不同字母的数目必须小于等于 maxLetters 。
- 子串的长度必须大于等于 minSize 且小于等于 maxSize 。
示例 1:
输入:s = "aababcaab", maxLetters = 2, minSize = 3, maxSize = 4
输出:2
解释:子串 "aab" 在原字符串中出现了 2 次。
它满足所有的要求:2 个不同的字母,长度为 3 (在 minSize 和 maxSize 范围内)。
示例 2:
输入:s = "aaaa", maxLetters = 1, minSize = 3, maxSize = 3
输出:2
解释:子串 "aaa" 在原字符串中出现了 2 次,且它们有重叠部分。
示例 3:
输入:s = "aabcabcab", maxLetters = 2, minSize = 2, maxSize = 3
输出:3
示例 4:
输入:s = "abcde", maxLetters = 2, minSize = 3, maxSize = 3
输出:0
提示:
- 1 <= s.length <= 10^5
- 1 <= maxLetters <= 26
- 1 <= minSize <= maxSize <= min(26, s.length)
- s 只包含小写英文字母。
解题思路
这道题目有一个很巧妙的地方在于,我们只需要考虑minSize
即可,举个例子:
假设我们子字符串的长度范围为 [2,4],并且允许的最大不同字符数为 4,那么所有满足需求的长度为 4 的子字符串,它的每一次重复里一定至少包含一次长度为 2 的子字符串。例如对于字符串 "abcdefghabcd",其中 "abcd" 重复了两次,那么至少 "ab" 也重复了两次。
代码如下
class Solution {
public:
int maxFreq(string s, int maxLetters, int minSize, int maxSize) {
int len=s.size();
map<string, int> counts;//存储每个满足条件的子串的出现次数
int hash[26]={0};//每个字母出现的次数
int res=0;//结果
int left=0;//左指针
int unique=0;//统计出现了多少个不同的字母
for(int right=0; right<len; right++)
{
if(hash[s[right]-'a']++==0)
unique++;//统计字符串中出现的不同字母个数
//当条件不满足时,移动左指针,直到条件满足
while(unique>maxLetters || right-left+1>minSize)
{
if(hash[s[left++]-'a']-- == 1)//移动左指针
unique--;
}
//条件满足时,更新答案,只考虑minSize
if(right-left+1==minSize)
{
string cur=s.substr(left,minSize);
if(counts.count(cur))//已经出现过了,次数加1
counts[cur]++;
else
counts.insert(make_pair(cur,1));//未出现过,插入到map中
res=max(res,counts[cur]);
}
}
return res;
}
};
提交结果: