python括号匹配问题_支持通配符的括号匹配问题源码+详细流程代码(python)
問題:
判斷一個有左括號和右括號、以及其他ASCII字符組成的表達式是合法。 判斷條件是左括號-右括號數目、次序配對,可多層嵌套。如果有*,則*可作為0個或者1個右括號,如果匹配則輸出ok,不匹配則輸出不匹配字符所在字符串中的具體位置
示例:
((((***********))(((**? ? ? ? ? ?不匹配字符位置:18 結果:NOK
((((***********))(((**))? ? ? ? ?結果:OK
(()())((()))(()***)? ? ? ? ? ? ? ? ?結果:OK
(()*)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??結果:OK
*(()*()()*(((*? ? ? ? ? ? ? ? ? ? ??不匹配字符位置:12 結果:NOK
(((())))*()(*((**? ? ? ? ? ? ? ? ??結果:OK
((()(())*? ? ? ? ? ? ? ? ? ? ? ? ? ??不匹配字符位置:1 結果:NOK
((**)(*())))? ? ? ? ? ? ? ? ? ? ? ??不匹配字符位置:12 結果:NOK
***(((()())**? ? ? ? ? ? ? ? ? ? ? ?結果:OK
(*))? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??不匹配字符位置:4 結果:NOK
()(())*(*)(? ? ? ? ? ? ? ? ? ? ? ? ??不匹配字符位置:11 結果:NOK
((((******))(((**? ? ? ? ? ? ? ? ? 不匹配字符位置:13 結果:NOK
分析:
在字符串中,如果有右括號,則優先匹配右括號,再考慮是否要進行通配符匹配。因此,可以先求出通配符*最少需要多少個才能滿足字符串中所有的的左括號匹配,計算公式為:
if? 左括號數量 <= 右括號數量://右括號大于等于左括號,不用通配符*替換
max_replace_num=0
else://右括號比左括號少,如果有*則需要用*進行替換右括號
max_replace_num=左括號數量-右括號數量
因括號匹配問題是優先最近原則,因此,可以將左括號入棧,如果遇到右括號,從棧中彈出一個與之匹配,如果遇到通配符*,如果max_replace_num==0則直接跳過,否則先入隊列,優先讓右括號先進行匹配,等到再碰到下一個左括號時先讓隊列中的通配符*優先匹配完棧中的左括號,再讓左括號入棧。
具體流程圖:
詳細代碼:
def append_list(i,ch):
ch_list = []
ch_list.append(i)
ch_list.append(ch)
return ch_list
def breaket_match(one_str):
'''
:param one_str: 需要匹配的字符串
:return: 返回-1則說明匹配,否則返回不匹配位置
'''
left_len = one_str.count('(') #左括號個數
left_list = [] # 臨時存放左括號字符串列表
right_list=[] #保存*的隊列
if left_len <= one_str.count(')'): #右括號大于等于左括號,不用*替換
max_replace_num=0
else: #右括號比左括號少,如果有*則需要用*進行替換右括號
max_replace_num=left_len-one_str.count(')') #替換個數為左括號減去右括號個數
for i in range(len(one_str)):
if one_str[i] == '(': #碰到第一個左括號,把標志位設置為false,說明從這里加上進行正式匹配
flag=False
if len(right_list)==0:
left_list.append(append_list(i=i,ch=one_str[i])) #當前左括號和左括號位置入棧
else: #*替換最大可替換個數
k=len(right_list)
tmp_replace = max_replace_num
for j in range(k):
if len(left_list)==0 or j >tmp_replace-1:
break
else:
left_list.pop()
max_replace_num -= 1
right_list.clear()
left_list.append(append_list(i=i, ch=one_str[i])) # 當前*和*位置入棧
elif one_str[i] == ')':#如果當前字符時右括號,出棧
if len(left_list) != 0: # 如果棧中有元素與之匹配,沒有元素,說明不匹配,返回位置
left_list.pop()
else:
return i + 1 # 不匹配,返回位置信息
else: #如果當前字符是*
if max_replace_num==0: #判斷*是否需要進行右括號匹配,為0說明不需要進行替換
pass
else: #*需要替換為右括號
if len(left_list)!=0 : #如果棧中有元素與之匹配,沒有元素,說明不匹配,返回位置,并且替*換個數-1
right_list.append(append_list(i=i, ch=one_str[i])) # 左括號和左括號位置入棧
else: #如果左括號個數為0,但是下一個與之匹配的為*,則跳過
pass
k = len(right_list)
tmp_replace=max_replace_num
for i in range(k):
if len(left_list) == 0 or i > tmp_replace-1:
break
else:
left_list.pop()
max_replace_num -= 1
if (len(left_list)!=0): #如果左括號棧中元素不為空,不匹配,返回位置信息
return left_list.pop()[0]+1
else:
return -1 #匹配,返回-1
def read_file(file_path):
'''
讀取文件
:param file_path:
:return: 返回list集合,里面包含文件每一行的字符
'''
lines = []
try:
file = open(file_path) #打開文件
line = file.readline() #讀取文件第一行
while 1:
line = line.strip('\n') #去掉換行符\n
lines.append(line) #把文件的每一行append到lines里面
line = file.readline()
if not line:
file.close()
break
except :
print("打開文件失敗,請確認文件名和路徑是否正確!")
return lines
def main():
# print("請輸入文本文件路徑:")
#讀取文件
# filepath=input() #讀取控制臺誰的文件路徑
lines=read_file("test.txt")
length_lines=len(lines)
#breaket_match(str)輸入參數str為需要匹配的字符串,如果匹配成功,則返回true,如果匹配不成功,則返回false
file=open("result.txt","w")
for i in range(length_lines): #對讀取出來的文件每一行進行匹配
result=breaket_match(one_str=lines[i])
if result==-1:
file.write("行號:第"+str(i+1)+"行; "+"源字符串:"+lines[i]+"; "+"結果:"+"OK"+"\n")
print("行號:第"+str(i+1)+"行; "+"源字符串:"+lines[i]+"; "+"結果:"+"OK")
else:
file.write("行號:第" + str(i+1) + "行; " + "源字符串:" + lines[i] + "; " +"不匹配字符位置:"+str(result)+ " 結果:" + "NOK"+"\n")
print("行號:第" + str(i+1) + "行; " + "源字符串:" + lines[i] + "; " +"不匹配字符位置:"+str(result)+ " 結果:" + "NOK")
file.close()
if __name__ == '__main__':
main()
總結
以上是生活随笔為你收集整理的python括号匹配问题_支持通配符的括号匹配问题源码+详细流程代码(python)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ArcGIS生成根据点图层生成等值面并减
- 下一篇: python dataframe 查看为