classSolution: defminCut(self, s: str) -> int: # 返回 s[l:r+1] 是否为回文串 @cache # 缓存装饰器,避免重复计算 is_palindrome(一行代码实现记忆化) defis_palindrome(l: int, r: int) -> bool: if l >= r: returnTrue return s[l] == s[r] and is_palindrome(l + 1, r - 1)
@cache # 缓存装饰器,避免重复计算 dfs(一行代码实现记忆化) defdfs(r: int) -> int: if is_palindrome(0, r): # 已是回文串,无需分割 return0 res = inf for l inrange(1, r + 1): # 枚举分割位置 if is_palindrome(l, r): res = min(res, dfs(l - 1) + 1) # 在 l-1 和 l 之间切一刀 return res
return dfs(len(s) - 1)
3297.统计重新排列后包含另一个字符串的子字符串数目1(1847)
给你两个字符串 word1 和 word2 。
如果一个字符串 x 重新排列后,word2 是重排字符串的 前缀 ,那么我们称字符串 x 是 合法的 。
# t 的字母出现次数与 s 的字母出现次数之差 diff = defaultdict(int) # 也可以用 Counter(t),但是会慢很多 for c in t: diff[c] += 1
# 窗口内有 less 个字母的出现次数比 t 的少 less = len(diff)
ans = left = 0 for c in s: diff[c] -= 1 if diff[c] == 0: # c 移入窗口后,窗口内 c 的出现次数和 t 的一样 less -= 1 while less == 0: # 窗口符合要求 if diff[s[left]] == 0: # s[left] 移出窗口之前,检查出现次数, # 如果窗口内 s[left] 的出现次数和 t 的一样, # 那么 s[left] 移出窗口后,窗口内 s[left] 的出现次数比 t 的少 less += 1 diff[s[left]] += 1 left += 1 ans += left return ans
3019.按键变更的次数(1176)
给你一个下标从 0 开始的字符串 s ,该字符串由用户输入。按键变更的定义是:使用与上次使用的按键不同的键。例如 s = “ab” 表示按键变更一次,而 s = “bBBb” 不存在按键变更。