这道来自上海计算机学会2026年2月月赛丙组的编程题目,表面看起来是一个数学展开式问题,实则考察选手对递归算法和动态规划思想的掌握程度。题目给出一个形如"a(b,c(d,e))"的嵌套字符串,要求将其展开为"a b d e c d e"的形式,即外层元素需要重复内层展开结果。
这类字符串解析与展开问题在实际开发中并不少见,比如配置文件解析、模板引擎处理、数据格式转换等场景都会遇到类似需求。题目设计的巧妙之处在于通过简单的规则隐藏了递归嵌套这一关键特征,需要选手透过现象看本质。
根据常见的竞赛题目设置规范,我们可以推测该题的输入输出要求如下:
输入格式:
输出格式:
示例分析:
输入 "a(b,c(d,e))"
正确输出应为 "a b d e c d e"
错误输出示例:
采用递归下降法解析字符串是最直观的解决方案。遇到字母时直接输出,遇到括号时递归处理内部内容,并将外层元素与递归结果组合。具体步骤如下:
python复制def expand(s):
res = []
i = 0
while i < len(s):
if s[i].isalpha():
res.append(s[i])
i += 1
elif s[i] == '(':
# 找到匹配的右括号
balance = 1
j = i + 1
while j < len(s) and balance > 0:
if s[j] == '(': balance += 1
elif s[j] == ')': balance -= 1
j += 1
# 递归处理括号内容
inner = expand(s[i+1:j-1])
# 外层元素需要重复内层结果
prefix = res[-1] if res else ''
res.pop() if res else None
for part in inner.split():
res.append(prefix + ' ' + part)
i = j
elif s[i] == ',':
i += 1
return ' '.join(res)
对于极端嵌套情况,纯递归可能导致栈溢出。可以采用记忆化技术存储已处理过的子串结果:
python复制from functools import lru_cache
@lru_cache(maxsize=None)
def expand_memo(s):
# 实现与之前类似,但会缓存结果
...
使用栈结构模拟递归过程,避免系统栈开销:
python复制def expand_iter(s):
stack = []
current = []
i = 0
while i < len(s):
if s[i].isalpha():
current.append(s[i])
i += 1
elif s[i] == '(':
stack.append(current)
current = []
i += 1
elif s[i] == ')':
inner = ' '.join(current)
outer = stack.pop()
new_current = []
for prefix in outer:
for part in inner.split():
new_current.append(prefix + ' ' + part)
current = new_current
i += 1
elif s[i] == ',':
i += 1
return ' '.join(current)
对于竞赛场景,当字符串长度达到上限时,可以考虑以下优化:
python复制from io import StringIO
def expand_optimized(s):
buf = StringIO()
# 优化实现...
return buf.getvalue().strip()
如果将题目改为需要计算展开后的字符串长度,而非输出具体内容,可以采用数学方法:
这种变形在竞赛中也很常见,考察选手对问题本质的理解和数学建模能力。