问题描述
小S有一个长度为n的字符串 s,她可以进行一种特殊的操作——将字符串中的部分折叠为回文子串。每次操作时,可以选择其中一个回文子串的左侧或右侧的部分折叠成一个子串,折叠的次数不限(可以折叠0次)。小S想知道,通过这种操作可以生成多少种不同的字符串。
例如,"aba"向左可以折叠成"ab"。"abba"向右可以折叠成"ba"。
测试样例 样例1:
输入:n = 3, s = "aba" 输出:3
样例2:
输入:n = 5, s = "aabaa" 输出:8
样例3:
输入:n = 4, s = "abba" 输出:4
问题本质
1. 回文折叠的特点
折叠的核心是 回文性: 任何回文子串都可以被作为操作的基础。 一个回文串可以选择折叠其左侧或右侧,从而缩短字符串长度。
2. 目标分析
通过回文折叠,我们需要统计所有可能生成的 不同字符串 的数量:
原字符串中所有 回文子串 是问题的关键。 每个回文子串都会提供若干种折叠方式,产生新的字符串。
3. 问题转化
找出字符串中所有的回文子串。 根据这些回文子串,模拟所有可能的折叠结果,并记录生成的 唯一字符串。
解题思路
1. 找出所有回文子串
使用 中心扩展法,可以高效地枚举字符串中所有的回文子串。 对每个回文子串 s[l:r],记录它的左右边界。
2. 模拟折叠过程
遍历所有回文子串,对其左右进行折叠操作: 左折叠:保留左侧部分字符串。 右折叠:保留右侧部分字符串。
3. 去重计数
将所有可能的折叠结果存储在一个集合中,以确保只统计不同的字符串。
代码实现
def count_folded_strings(n, s):
"""统计通过回文折叠可以生成的不同字符串数量"""
def find_palindromes(s):
"""找到字符串中所有的回文子串及其边界"""
palindromes = []
for center in range(len(s)):
# 奇数长度回文
l, r = center, center
while l >= 0 and r < len(s) and s[l] == s[r]:
palindromes.append((l, r))
l -= 1
r += 1
# 偶数长度回文
l, r = center, center + 1
while l >= 0 and r < len(s) and s[l] == s[r]:
palindromes.append((l, r))
l -= 1
r += 1
return palindromes
# Step 1: 找到所有回文子串
palindromes = find_palindromes(s)
# Step 2: 通过回文折叠生成所有可能的字符串
results = set()
for l, r in palindromes:
# 原始回文子串
results.add(s[l:r+1])
# 左侧折叠
results.add(s[:l] + s[l:r+1])
# 右侧折叠
results.add(s[l:r+1] + s[r+1:])
# 返回不同字符串的数量
return len(results)
# 测试用例
if __name__ == "__main__":
print(count_folded_strings(3, "aba")) # 输出: 3
print(count_folded_strings(5, "aabaa")) # 输出: 8
print(count_folded_strings(4, "abba")) # 输出: 4
解题详解
(1) 寻找回文子串
使用 中心扩展法,以字符串中的每个字符为中心,向左右扩展寻找回文子串。 通过同时考虑 奇数长度 和 偶数长度 回文,能高效地覆盖所有可能。
(2) 模拟折叠操作
对每个回文子串,进行以下三种处理: 原始子串直接作为结果。 左侧折叠,保留左侧部分。 右侧折叠,保留右侧部分。
(3) 去重处理
通过使用 Python 的集合 set,自动去除重复字符串。
复杂度分析
1. 时间复杂度
中心扩展法:查找所有回文子串的复杂度为 O(n的2次方)。 折叠模拟:每个回文子串的处理操作复杂度为 O(1)。 总复杂度:O(n的2次方)。
2. 空间复杂度
结果存储的集合复杂度为 O(k),其中 k 为生成的不同字符串数量。