匹配输入文本中的平衡大括号和嵌套大括号

Matching balanced and nested braces in input text

本文关键字:嵌套 平衡 输入 文本      更新时间:2023-10-16

我参加了一个测验,我给出了代码,但自动测试显示八个测试用例中的一个失败了。我自己测试了我的代码很多次,但都通过了。我找不到问题出在哪里。

问题是设计一种算法来检查字符串中的括号是否匹配。

1)只考虑圆角括号()和方括号[],省略其他字符。
2)每对括号应相互匹配。这意味着匹配)[匹配]
3)不允许交叉,如:([)]。有两对括号,但它们相互交叉。

为了解决这个问题,我的方法描述如下:

  1. 搜索整个输入字符串中的每个字符,索引从 0 到 str.size() - 1。
  2. 使用两个堆栈记录开始标记 ([ ,每个类型都在一个堆栈中。遇到其中一个时,将其索引推送到相应的堆栈中。
  3. )]的结束标签被编码时,我们弹出相应的堆栈。
  4. 在弹出之前,检查两个堆栈的顶部,当前堆栈应该有 max 索引,否则这意味着与其他类型存在不匹配的开放标签,因此可以通过这种方式检查交叉。

我的代码在这里:

#include <iostream>
#include <stack>
using namespace std;
int main()
{
    string str;
    cin >> str;
    stack<int> s1, s2;
    int result = 0;
    for (int ix = 0, len = str.size(); ix < len; ix++)
    {
        if (str[ix] == '(')
        {
            s1.push(ix);
        }
        else if (str[ix] == '[')
        {
            s2.push(ix);
        }
        else if (str[ix] == ')')
        {
            if (s1.empty() || (!s2.empty() && s1.top() < s2.top()))
            {
                result = 1;
                break;
            }
            s1.pop();
        }
        else if (str[ix] == ']')
        {
            if (s2.empty() || (!s1.empty() && s2.top() < s1.top()))
            {
                result = 1;
                break;
            }
            s2.pop();
        }
        else
        {
            // do nothing
        }
    }
    if (!s1.empty() || !s2.empty())
    {
        result = 1;
    }
    cout << result << endl;
}

如前所述,这个问题可以通过堆栈来解决,所以我修改了我的代码,这里是单堆栈版本。[关键点不是争论 WITCH 更好,而是我的代码有什么问题。

#include <iostream>
#include <stack>
using namespace std;
int main()
{
    string str;
    cin >> str;
    stack<char> s;
    const char *p = str.c_str();
    int result = 0;
    while (*p != '')
    {
        if (*p == '(' || *p == '[')
        {
            s.push(*p);
        }
        else if (*p == ')')
        {
            if (s.empty() || s.top() != '(')
            {
                result = 1;
                break;
            }
            s.pop();
        }
        else if (*p == ']')
        {
            if (s.empty() || s.top() != '[')
            {
                result = 1;
                break;
            }
            s.pop();
        }
        else
        {
            // do nothing
        }
        p++;
    }
    if (!s.empty())
    {
        result = 1;
    }
    cout << result << endl;
}

当使用格式化输入读取std::string时,只读取第一个单词:跳过前导白字后,将读取一个字符串,直到遇到第一个空格。因此,输入( )应匹配,但std::cin >> str只会读取(。因此,输入可能如下所示:

if (std::getline(std::cin, str)) {
    // algorithm for matching parenthesis and brackets goes here
}

使用 std::getline() 仍然会假设输入的呈现方式,即它在一行上。如果算法应该处理来自std::cin的整个输入,我会使用

str.assign(std::istreambuf_iterator<char>(std::cin),
           std::istreambuf_iterator<char>());

虽然我认为该算法是不必要的复杂(在堆栈存储上,括号就足够了),但我也认为它应该有效,即我发现的唯一问题是获取输入的方式。