题目描述:
给你一个字符串 word
和一个 非负 整数 k
。
返回 word
的 子字符串 中,每个元音字母('a'
、'e'
、'i'
、'o'
、'u'
)至少 出现一次,并且 恰好 包含 k
个辅音字母的子字符串的总数。
代码思路:
主函数逻辑
- 计算
f(k)
和f(k+1)
的差值,这样可以得到恰好包含至少k
个辅音字母的子字符串数量。 f(k)
计算的是包含至少k
个辅音字母的子字符串数量,而f(k+1)
计算的是包含至少k+1
个辅音字母的子字符串数量。- 它们的差即为包含恰好
k
个辅音字母的子字符串数量。
函数 f(k)
的作用
- 输入与初始化:
- 输入是字符串
word
和整数k
。 - 计算字符串的长度
n
。 - 使用一个计数器
cnter
来记录当前子字符串中各个字符的出现次数。 - 初始化指针
j
为 0,用于表示当前子字符串的起始位置。 - 初始化结果变量
ans
为 0,用于累计满足条件的子字符串数量。
- 输入是字符串
- 滑动窗口遍历字符串:
- 使用
for
循环和指针i
从头到尾遍历字符串word
。 - 对每个字符
w
,在计数器cnter
中增加其计数。
- 使用
- 检查并调整窗口:
- 在每次移动
i
后,检查当前窗口[j, i]
是否满足条件:包含所有五个元音字母,且辅音字母数量不少于k
。 - 条件检查:
cnter['a']
,cnter['e']
,cnter['i']
,cnter['o']
,cnter['u']
都大于 0。- 窗口内的辅音数量
i - j + 1 - (cnter['a'] + cnter['e'] + cnter['i'] + cnter['o'] + cnter['u'])
大于等于k
。
- 如果满足条件,移动
j
指针以缩小窗口,直到不再满足条件为止:- 减少
word[j]
在cnter
中的计数。 - 增加
j
。
- 减少
- 在每次移动
- 累计结果:
- 每次调整完窗口后,将
j
加到ans
中。这里j
表示以当前i
为结尾的满足条件的子字符串的数量。
- 每次调整完窗口后,将
- 返回结果:
- 函数
f(k)
返回满足条件的子字符串总数。
- 函数
代码实现:
class Solution:
def countOfSubstrings(self, word: str, k: int) -> int:
n = len(word)
def f(k): # 表示每个元音至少出现一次且辅音至少出现k次的子字符串总数
ans = 0
cnter = Counter()
j=0 # [i,j] 表示此时刚好不满足要求的子字符串下标区间
for i,w in enumerate(word):
cnter[w] += 1
while cnter['a'] and cnter['e'] and cnter['i'] and cnter['o'] and cnter['u'] and \
i-j+1-(cnter['a']+cnter['e']+cnter['i']+cnter['o']+cnter['u'])>=k:
cnter[word[j]] -= 1
j += 1
ans += j # 表示 word[0~i]与word[j-1~i]都满足条件,将他们都记录到答案中,一共有j个
return ans
return f(k)-f(k+1)