支持通配符的括号匹配问题源码+详细流程代码(python)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u011128775/article/details/78861185

问题:

判断一个有左括号和右括号、以及其他ASCII字符组成的表达式是合法。 判断条件是左括号-右括号数目、次序配对,可多层嵌套。如果有*,则*可作为0个或者1个右括号,如果匹配则输出ok,不匹配则输出不匹配字符所在字符串中的具体位置

源码下载地址:http://download.csdn.net/download/u011128775/10167555#comment

示例:

((((***********))(((**           不匹配字符位置: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()

源码+visio流程图+测试用例下载地址:http://download.csdn.net/download/u011128775/10167555#comment

展开阅读全文

没有更多推荐了,返回首页