LeetCode 395. 至少有K个重复的最长子串

题目描述

给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于 k 。返回这一子串的长度。

示例1:

输入:s = "aaabb", k = 3
输出:3
解释:最长子串为 "aaa" ,其中 'a' 重复了 3 次。

示例2:

输入:s = "ababbc", k = 2
输出:5
解释:最长子串为 "ababb" ,其中 'a' 重复了 2 次, 'b' 重复了 3 次。

提示:

  • 1 <= s.length <= 104
  • s 仅由小写英文字母组成
  • 1 <= k <= 105

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-with-at-least-k-repeating-characters

思路解析

直接采用暴力枚举的方法不可取,时间复杂度为 \(O(n^3)\),想办法降低时间复杂度。这里采用分治的方法来加速。

  1. 若某一字符 cs 中出现的次数小于 k 次,那么可以确定最长的子串一定不包含 c,可以将 s 在所有 c 出现的地方进行分割,然后计算各个分割得到的子串中符合要求的最大子串。
  2. 若不存在这样的字符 c,那么直接返回 s 的长度即可。

代码实现

class Solution {
public:
    int longestSubstring(string s, int k) {
        if(s.empty()) return 0;
        unordered_map<char, vector<int>> smap;
        for(int i = 0; i < s.length(); i++) {
            smap[s[i]].push_back(i);
        }
        for(auto p : smap) {
            if(p.second.size() < k) {
                int maxLen = longestSubstring(s.substr(0, p.second[0]), k);
                for(int i = 0; i < p.second.size(); i++) {
                    int nextPos = (i == p.second.size() - 1) ? s.length() : p.second[i + 1];
                    string tmpStr = s.substr(p.second[i] + 1, nextPos - p.second[i] - 1);
                    int tmpLen = longestSubstring(tmpStr, k);
                    maxLen = max(maxLen, tmpLen);
                }
                return maxLen;
            }
        }
        return s.length();
    }
}; 
posted @ 2021-02-27 13:43  行者橙子  阅读(109)  评论(0编辑  收藏  举报