蓝桥杯 正则问题
题目描述
考虑一种简单的正则表达式:只由 x ( ) | 组成的正则表达式。求这个正则表达式能接受的最长字符串的长度。
例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是 xxxxxx,长度是 6。
输入:一个由 x ( ) | 组成的正则表达式,长度不超过 100,保证合法。
输出:能接受的最长字符串的长度。
解题方法:栈模拟
核心思路是用栈来模拟正则表达式的求值过程。正则中的 | 表示"或"(取较长的那条路),() 表示分组,x 串联表示连接。
把 x 的连续个数压栈,| 和 ( 也作为标记入栈。遇到 ) 时出栈直到 (,收集所有 | 分隔的数字,取最大值,然后重新压入对应数量的 x。
最后处理栈中残余的 | 分隔,取最大值即为答案。
算法思路
- 遍历每个字符,用栈维护状态
x→ 栈顶数字 +1(连续x计数),或者栈为空 / 栈顶不是数字 → 压入 1|→ 作为分隔标记入栈(→ 作为标记入栈)→ 出栈直到(:收集过程中以|分隔的所有数字,取最大值,将对应数量的x重新压回栈- 扫描结束后,栈中剩下的
|分隔的各个数字取最大值
代码解析
s = input().strip()
stk = []
for ch in s:
if ch == ')':
# 收集当前括号组内的所有选项
nums = []
cur = 0
while True:
x = stk.pop()
if x == 'x':
cur += 1
elif x == '|' or x == '(':
nums.append(cur)
cur = 0
if x == '(':
break
# 取最长选项,压回栈
stk.extend(list('x' * max(nums)))
else:
stk.append(ch)
# 处理栈中剩余的 | 分隔
nums = []
cur = 0
for ch in stk:
if ch == 'x':
cur += 1
elif ch == '|':
nums.append(cur)
cur = 0
nums.append(cur)
print(max(nums))代码要点
- 栈的优势:用栈天然支持括号嵌套,遇到
)时栈顶到(之间的内容就是当前分组 |的处理:遇到|时先把当前累计的cur存起来,然后归零继续计数。最后nums里存的就是该组内所有|分支的x数量- 合并逻辑:
取 max就是|的语义——选最长的那个分支
复杂度分析
- 时间复杂度:O(n²),最坏情况下每个
)需要出栈 O(n) 个元素再压回去 - 空间复杂度:O(n),栈的大小
这道题的关键在于意识到这就是一个"用栈做表达式求值"的问题,把正则的元字符映射为栈操作即可,不需要真的去搞正则引擎。