題目描述
??考慮一種簡單的正則表達式:
??只由 x ( ) | 組成的正則表達式。
??小明想求出這個正則表達式能接受的最長字符串的長度。
??例如 ((xx|xxx)x|(x|xx))xx 能接受的最長字符串是: xxxxxx,長度是 6。
輸入描述
??一個由 x()| 組成的正則表達式。輸入長度不超過 100,保證合法。
輸出描述
??這個正則表達式能接受的最長字符串的長度。
輸入輸出樣例
示例
輸入
((xx|xxx)x|(x|xx))xx
輸出
6
題目解析
((xx|xxx)x|(x|xx))xx 該表達式為什么最大可接受的字符串長度是6?
先明白算法規則:
??“|” 代表的是分支,比如 “xx|xxx” 就代表字符串有兩種可能性,一種是xx,另外一種是xxx,所以,我們需要判斷哪個分支能接受更多的字符串,在每個分支中,每遇到一個"x",可接受的字符串長度就+1;
??“()”代表的是優先級,也就是深度,每當遇到“(”,我們都需要進行遞歸調用進入下一層,當遇到“)”,則結束調用返回上一層。
((xx|xxx)x|(x|xx))xx 這個表達式用一個類似于二叉樹的結構表示是這樣的:
??通過上圖明顯可以看出,(xx|xxx)x 這一段,最大可接受的字符串長度為4,(x|xx)這一段,最大可接受的字符串長度為2,(xx|xxx)x 和 (x|xx) 處在同一層,用“|” 分開,所以 ((xx|xxx)x|(x|xx)) 取得這兩個分支中的最大可接受的字符串長度為4,然后原字符串后面還有兩個 “xx”,相加之后,該正則表達式的最大可接受的字符串長度就是 4 + 2 = 6 個。
程序步驟
??這個算法通過深度優先搜索的方式,遍歷整個正則表達式,對于每個 ( 會進入新的遞歸調用,對于 | 會進行分支處理,對于 x 會增加當前長度,對于 ) 會更新結果并返回,最終得到能接受的最長字符串的長度。
- 首先,程序從輸入中讀取一個由 x、(、)、| 組成的正則表達式,并存儲在變量 s 中。
- 初始化兩個變量 pos 和 length,分別表示當前處理的位置和輸入字符串的長度。
- 定義一個名為 dfs 的深度優先搜索函數:
??函數內部使用 ans 存儲最終的最大長度,temp 存儲當前正在處理的長度。
??進入 while 循環,只要 pos 小于 length,就會不斷進行以下操作:
????當遇到 ( 時,將 pos 加一,然后遞歸調用 dfs 函數,并將其結果累加到 temp 中。
????當遇到 x 時,將 pos 加一,同時 temp 加一,表示找到了一個 x,長度加一。
????當遇到 | 時,將 pos 加一,更新 ans 為 ans 和 temp 中的最大值,將 temp 重置為 0,意味著開始新的分支處理。
????當遇到 ) 時,將 pos 加一,更新 ans 為 ans 和 temp 中的最大值,將 temp 重置為 0,同時返回 ans。
??循環結束后,處理類似 xx|xxxxx 這樣的情況,更新 ans 為 ans 和 temp 中的最大值。 - 調用 dfs 函數,并將結果存儲在 x 中。
- 打印出最終結果。
代碼實現
感謝 @李時城 同學提供的代碼,這是添加注釋之后的版本。
import os
import sys# 讀取輸入的正則表達式
s = input()
# 初始化位置和長度
pos, length = 0, len(s)def dfs():# 聲明使用全局變量 pos 和 lengthglobal pos, length# 存儲最終結果和臨時結果ans, temp = 0, 0while pos < length:# 遇到左括號,位置加一,遞歸調用 dfs 函數,并將結果累加到 temp 中if s[pos] == '(':pos += 1temp += dfs()# 遇到 'x',位置加一,temp 加一elif s[pos] == 'x':pos += 1temp += 1# 遇到 '|',位置加一,更新 ans 為 ans 和 temp 中的最大值,重置 tempelif s[pos] == '|':pos += 1ans = max(ans, temp)temp = 0# 遇到右括號,位置加一,更新 ans 為 ans 和 temp 中的最大值,返回 anselif s[pos] == ')':pos += 1ans = max(temp, ans)# temp = 0return ans# 處理類似 xx|xxxxx 的情況ans = max(ans, temp)return ans# 調用 dfs 函數
x = dfs()
print(x)