文章目录
正则问题
题目描述
考虑一种简单的正则表达式:
只由 x ( ) | 组成的正则表达式。
小明想求出这个正则表达式能接受的最长字符串的长度。
例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是: xxxxxx,长度是 6。
输入描述
一个由 x()| 组成的正则表达式。输入长度不超过 100,保证合法。
输出描述
这个正则表达式能接受的最长字符串的长度。
样例输入
((xx|xxx)x|(x|xx))xx
样例输出
6
样例解释
正则表达式,又称规则表达式,通常被用来检索、替换符合某个模式(规则)的文本。
比如题目中由“ x ( ) | ”组成的正则表达式,括号“()”的优先级最高,或操作“|”次之。括号里面是一个整体,或的两边保留最长的一个。
((xx|xxx)x|(x|xx))xx 是怎么执行的,为什么是 6 呢?
先执行括号,再执行或,步骤是:
先看第一个括号,发现里面还有嵌套括号,找到最内部的括号,括号内是一个或操作。((xx|xxx)x|(x|xx))xx,得:(xxxx|(x|xx))xx
继续执行最内部括号。(xxxx|(x|xx))xx,得:(xxxx|xx)xx
继续执行最后括号。(xxxx|xx)xx,得:xxxxxx,结束,得长度为 6 的字符串。
分析
- 可能是习惯反射吧,一看到有括号的问题我就会想到括号匹配这道题,会想用栈的结构去解决问题。事实证明,这样真可以。
- 我们这题肯定会用到dfs,因为括号不止一个,通过递归解决每一个小括号,这样就好办了。
- 首先,由于我们需要遍历每一个字符,所以定义一个
pos变量
,进行位置的记录,为避免
递归这个小朋友迷失方向
,我们把pos设为一个全局变量
,这样时刻就不会走到奇怪的位置了。 - 这里因为存在
或|
,所以必定有前后的比较,所以用两个变量ans,tmp
的比较来判断究竟哪边X比较多。 - 首先无论遍历到哪个字符,位置都要进行移动,即
pos+=1
- 进栈可能暂时还想不到干嘛,但出栈的时候,我们需要获取最大值,所以res和ans进行比较,我们以ans为最终结果,就
return ans
- 对于或符的处理,我们是这样做的,首先比较ans和tmp谁大取谁,
tmp一定要清零
,因为或后面的字符需要用tmp来统计。即或前用ans记录,或后用tmp记录
。 - 对于x的记录,使用tmp进行记录。
- 结束的时候我们就返回ans和tmp的最大值,相当于或前或者或后的值。
- 这里我们应该知道,在进栈的时候,应该做一件事情,就是tmp要改写值,因为tmp的值要给ans作为或前值的记录,所以这里必须要加,且需要在入栈加(因为一开始就需要统计了),这就是为什么我要在出栈设置返回值的缘故。
总体程序就是:我用tmp进行统计,将或前给ans,将或后给自己,再比较最大值即可。
代码
s = input()
pos = 0
def dfs(s):
global pos
n = len(s)
ans = 0
tmp = 0 # 记录另外一边(与res比较)
while pos < n:
if s[pos] == '(': # 进栈
pos+=1
tmp += dfs(s)
elif s[pos] == ')': # 出栈
pos+=1
ans = max(ans,tmp)
return ans
elif s[pos] == '|': # 处理或符之前的值
pos+=1
ans = max(ans,tmp)
tmp = 0
else: # 记录x
pos+=1
tmp+=1
ans = max(ans,tmp)
return ans
print(dfs(s))
通过截图
寒假作业
题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
现在小学的数学题目也不是那么好玩的。 看看这个寒假作业:
□ + □ = □
□ - □ = □
□ × □ = □
□ ÷ □ = □
每个方块代表 1~13 中的某一个数字,但不能重复。
比如:
6 + 7 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5
以及:
7 + 6 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5
就算两种解法。(加法,乘法交换律后算不同的方案)
你一共找到了多少种方案?
运行限制
最大运行时间:1s
最大运行内存: 128M
分析
- 一看就知道是全排列问题,枚举
13!
是会超时的,所以不提倡(由于是填空所以超时不可怕,可怕的是在比赛中跑不出来) - 而且我们知道肯定如果加减乘除有一个运算不行,后面就不用看了。
这不就是剪枝吗?
- 所以,这题我们使用
回溯算法
来做。 - 全排列数组设为nums,一开始用0初始化
- 标记数组设为vis,一开始也用0初始化,表示尚未标记
- 我们设几个计算函数为布尔类型(当然也可以直接写),这个有点简单,不刻意进行说明。
- 由于我们可能不知道我们取了几个数,所以这里用
num进行全排列数组长度的记录
,在我以前写全排列的时候,当时使用path数组记录可能的全排列,所以那时候,直接len就可以得到path取了几个,现在我们不用path,所以要另外取变量记录。 - 终止条件为什么是
num==13
呢?因为循环在终止条件下面,如果是num==12
的话,这时候nums[12]尚未构建好,所以一定要下一个数。
其他就是模板问题了。
代码
res = 0
nums = [0 for i in range(14)]
vis = [0 for i in range(14)] # 标记数组
def check3(): # 检查前3个
return nums[1]+nums[2] == nums[3]
def check6():
return nums[4]-nums[5] == nums[6]
def check9():
return nums[7]*nums[8] == nums[9]
def check12(): # 本来是nums[10]/nums[11] == nums[12],这样转化避免出现小数
return nums[11]*nums[12] == nums[10]
def dfs(num): # 参数num用来计数
global res
if num == 13: # 终止条件
if check12():
res+=1
return
# 剪枝
if num == 4 and not check3():
return
if num == 7 and not check6():
return
if num == 10 and not check9():
return
for i in range(1,14): # 从1到13取:
if not vis[i]: # 没被标记
nums[num] = i
vis[i] = 1 # 标记
dfs(num+1)
vis[i] = 0 # 回溯
dfs(1)
print(res)
通过截图
答案为:64
如有错误,敬请指正,欢迎交流,谢谢♪(・ω・)ノ