本题解采用了双指针法和哈希表来统计完全子字符串。首先,初始化一个长度为26的列表char_positions,用于存储每个字符在word中的出现位置。接着,遍历word中的每个字符,更新char_positions,并检查当前字符是否与前一个字符在字母表中的顺序相差超过2,如果是,则更新切割点cut。然后,检查当前字符出现的次数是否达到k次,如果达到,则调用check函数检查从pre(当前字符第k次出现的位置)到i(当前位置)的子字符串是否满足每个字符恰好出现k次的条件。如果满足,则增加答案计数器ans,并更新pre的位置,继续检查。最后,返回答案计数器ans。
时间复杂度: O(n^2)
空间复杂度: O(n)
class Solution:
def __init__(self):
self.char_positions = [[] for _ in range(26)] # 存储每个字符的出现位置
self.word = \"\"
self.k = 0
def check(self, left):
# 检查从left到right的子字符串是否满足每个字符恰好出现k次的条件
new_left = left
for i in range(26):
if self.char_positions[i]:
# 如果当前字符在[left, right]范围内出现
if self.char_positions[i][-1] >= left:
# 如果当前字符出现次数不足k或超过k
n = len(self.char_positions[i])
if n < self.k:
return -1
if n > self.k:
if new_left <= self.char_positions[i][n - self.k - 1]:
return -1
new_left = min(new_left,self.char_positions[i][n - self.k])
return new_left
def countCompleteSubstrings(self, word, k):
self.word = word
self.k = k
cut = 0 # 初始化切割点
ans = 0 # 初始化答案
for i in range(len(self.word)):
char_index = ord(self.word[i]) - ord(\"a\") # 当前字符的索引
self.char_positions[char_index].append(i) # 更新字符位置
# 如果相邻字符字母表顺序相差超过2,则更新切割点
if i and abs(char_index - (ord(self.word[i - 1]) - ord(\"a\"))) > 2:
cut = i
# 如果当前字符出现次数小于k,则继续
if len(self.char_positions[char_index]) < self.k:
continue
pre = self.char_positions[char_index][
len(self.char_positions[char_index]) - self.k
]
while pre >= cut:
new_pre = self.check(pre)
if new_pre == -1:
break
if new_pre == pre:
ans += 1
pre -= 1
else:
pre = new_pre
return ans