https://leetcode-cn.com/problems/longest-substring-with-at-least-k-repeating-characters/
思路:分治法,考虑区间
[
l
,
r
]
[l,r]
[l,r],统计其内每个字符的出现次数,然后看是否有字符不满足题意,若满足说明当前区间合法,返回有效长度
r
−
l
+
1
r-l+1
r−l+1;若不满足则任何含有该字符的区间(子字符串)都不满足题意,所以我们可以以这个字符为间断,把
[
l
,
r
]
[l,r]
[l,r]分为几个部分分治计算。
class Solution {
public:
int dfs(string &s,int l,int r,int k)
{
vector<int> cnt(26);
for(int i=l;i<=r;i++)
++cnt[s[i]-'a'];
char split=0;
for(int i=0;i<26;i++)
if(cnt[i]&&cnt[i]<k)
split=i+'a';
if(!split)
return r-l+1;
int ans=0;
while(1)
{
while(l<=r&&s[l]==split)
++l;
if(l>r)
break;
int beg=l;
while(l<=r&&s[l]!=split)
++l;
ans=max(ans,dfs(s,beg,l-1,k));
}
return ans;
}
int longestSubstring(string s, int k)
{
int n = s.size();
return dfs(s,0,n-1,k);
}
};
思路二:滑动窗口,直接滑是不行的,需要枚举最多出现的字符种类数,不妨设为 i i i,那么依据这个条件就可以维护窗口了。
class Solution {
public:
int longestSubstring(string s, int k)
{
int n = s.size(),l,r,ans=0;
for(int i=0;i<n;i++)
s[i]-='a';
for(int i=1;i<=26;i++)
{
l=r=0;
vector<int> cnt(26);
int numi=0,lessk=0;
while(r<n)
{
++cnt[s[r]];
if(cnt[s[r]]==1)
++numi,++lessk;
if(cnt[s[r]]==k)
--lessk;
while(numi>i)
{
--cnt[s[l]];
if(cnt[s[l]]==0)
--numi,--lessk;
if(cnt[s[l]]==k-1)
++lessk;
++l;
}
if(!lessk)
ans=max(ans,r-l+1);
++r;
}
}
return ans;
}
};