首页 > 试题广场 >

括号匹配

[编程题]括号匹配
  • 热度指数:2026 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

一般的括号匹配问题是这样的:

给出一个字符串,判断这个括号匹配是不是合法的括号匹配。

如"((" 和 "())"都不是合法的括号匹配,但是"()()()","(()())()"等就是合法的括号匹配。

这个问题解决起来非常简单,相信大家都知道怎么解决。

现在给出一个加强版的括号匹配问题: 给出n个由括号 '(' 和 ‘)’ 组成的字符串,请计算出这些字符串中有多少对字符串满足si + sj是合法的括号匹配。如果si + sj和s+ si都是合法的括号匹配(i ≠ j),那么这两种搭配都需要计入答案;如果对于sisi + si是合法的括号匹配,那么也需要计入答案。



输入描述:

第一行是一个整数n,表示字符串的个数;

接下来n行是n个非空字符串,全部由'('和')'组成。

1 <= n <= 3 * 105,字符串的长度之和不超过3 * 105



输出描述:
一个整数,表示满足条件的字符串对的数量。
示例1

输入

3
()
(
)

输出

2
示例2

输入

5
(()
)))))
()()()
(((
))

输出

1

基本思想是参考前面几位大佬们的思想:
找出只有”()“的串 -- num1
再找分别有”(“ 和”)"
最后通过二次循环遍历比较计算出第二种情况的-- "(...(" ")...)" 组合数量num2
最后得到 num1*num1 + num2
不过我这里先用正则表达式的sub 先将所有的"()"括号对都去掉了,最后只留下具有
"(" 和 ")" 进行对比。
不过最后二次遍历时,case通过率只有60%

后来发现是通过使用list的count方法通过了所有的case (使用单层循环)。


#!/usr/bin/env python3
# -*- coding: utf-8 -*-


import re


def handle(brack):

    while re.findall(r"[\(][\)]", brack) != []:
        brack = re.sub(r"[\(][\)]", "", brack)
    return brack


def main():
    num = int(input().strip())
    brackets_list = []
    brackets_list2 = []
    brackets_list3 = []
    num1 = 0
    num2 = 0
    for i in range(num):
        brackets_list.append(input().strip())

    for i in range(num):
        temp = handle(brackets_list[i])
        if temp == "":
            num1 += 1
        else:
            if list(temp)[0] == ")":
                brackets_list2.append(temp)
            elif list(temp)[0] == "(":
                brackets_list3.append(temp)
    for i in brackets_list3:
        num2 += brackets_list2.count(")"*len(i))
    result = num1*num1 + num2
    print(result)


if __name__ == '__main__':
    main()
		

编辑于 2018-10-19 22:28:36 回复(0)
思路参考WAK的:Python解法,算法复杂度过大,AC了90%
暴力求解,随机选择两个字符串,然后判断是否合法,只能达到部分ac,对于有些例子,时间复杂度太高。后面考虑先对字符串进行一遍是否合法的判断,将本身合法的取出,个数记为num1,将本身不合法的存入vector,进行暴力求解,个数记为num2,总个数为num1num1+num2,但还是时间复杂度太高。最后考虑,先对字符串进行一遍是否合法的判断,将本身合法的取出,个数记为num1,将本身不合法的字符串中间已匹配的括号去掉,只保留不匹配的部分,不匹配的部分只有这几种情况:全是左括号;全是右括号;先是部分右括号,然后左括号。这三种里面只有前两种在个数相同时,组合起来可以合法。所以将第一种情况的字符串长度存入vecl中,将第二种情况的字符串长度存入vecr中,两层for循环,找vecl中和vecr中相同的个数,记为num2,总数为num1num1+num2。全部ac。
# coding=utf-8
import sys
import math
num = int(sys.stdin.readline().strip())
string_list = []
for i in range(num):
    string = sys.stdin.readline().strip()
    string_list.append(string)
count = 0
def check(string):
    flag = True
    left, right = 0, 0
    for i in string:
        if i == '(':
            left += 1
        if i == ')':
            if left >0:
                left -= 1
            else:
                right += 1
        if left < right:              #出现右括号数量大于左括号数量,退出循环
            flag = False
            # return flag, left, right
    if left!= right:
        flag = False
    return flag,left,right
num1 = 0
num2 = 0
save_left =[]
save_right =[]
for string in string_list:
    flag,left,right = check(string)
    if flag :
        num1 += 1
        # print('s')
    else:
        if left == 0 and right != 0:
            save_right.append(right)
        elif left != 0 and right == 0:
            save_left.append(left)
# print(save_right,save_left)
for i in save_left :
    for j in save_right:
        if i == j:
            num2 += 1
print(num1*num1 + num2)
编辑于 2018-08-12 13:05:09 回复(0)