2953. 统计完全子字符串(将题目中给的信息进行分组循环)
思路:根据题目中所给的第二个信息我们可以提取到至多相差2,说明相邻字母相减的绝对值小于等于2,一共有26个字母,因此我们可以枚举有多种不同的字母,因此每个窗口的大小为m * k,即在该窗口内有m个不同的字母,每一个均出现k次,暴力滑动窗口即可(tips : 最后几个点实在过不去,可能是我用multiset的原因)
class Solution {
public:
int countCompleteSubstrings(string word, int k) {
//我去好神奇,这题
//设m为不同的个数
//可以转化为一个k * m大小的窗口里面有m个不同的字母出现k次,太神奇了wc
int n = word.size();
int sum = 0;
for(int m = 1; m <= 26; m ++)//将不同字母分组
{
int b[26] = {0}, cnt = 0;
char c = word[0];//记录窗口的上一个是什么字符
multiset<int>se;
for(int i = 0, j = 0; i < n && k * m <= n; i ++)
{
if(i - j + 1 < k * m)
{
b[word[i] - 'a'] ++;
if(b[word[i] - 'a'] == 1) cnt ++;
if(i != 0) se.insert(abs(word[i] - c));
c = word[i];
}
else {
b[word[i] - 'a'] ++;
if(b[word[i] - 'a'] == 1) cnt ++;//统计多少个不同的
if(i != 0 && m * k > 1) se.insert(abs(word[i] - c));
if(cnt == m)
{
int f = 0;
for(int o = 0; o <= 25; o ++)
{
if(b[o] != k && b[o] >= 1)
{
f = 1;
break;
}
}
int u = 0;
if(se.size() >= 1)
u = *se.rbegin();
if(!f && u <= 2) sum ++;
}//相当于有两个条件的判断
b[word[j] - 'a'] --;
auto it = se.find(abs(word[j + 1] - word[j]));//nmd忘记取绝对值了
if(it != se.end()) se.erase(it) ;//只删除一个
c = word[i];
if(b[word[j] - 'a'] == 0) cnt --;
j ++;
}
}
}
return sum;
}
};