【题目描述】
在某个字符串(长度不超过100)中有左括号、右括号和大小写字母;规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配。写一个程序,找到无法匹配的左括号和右括号,输出原来字符串,并在下一行标出不能匹配的括号。不能匹配的左括号用"$"标注,不能匹配的右括号用"?"标注。
【输入】
输入包括多组数据,每组数据一行,包含一个字符串,只包含左右括号和大小写字母,字符串长度不超过100。
【输出】
对每组输出数据,输出两行,第一行包含原始输入字符,第二行由"$","?"和空格组成,"$"和"?"表示与之对应的左括号和右括号不能匹配。
【输入样例】
((ABCD(x)
)(rttyy())sss)(
【输出样例】
((ABCD(x)
$$
)(rttyy())sss)(
? ?$
【解题思路】
这个题应该是放在栈这一章的,看到了官方配套的绿书训练指导上面给出的两个标程,其中一个就是用栈来做的,另外一个说是用“递归”,但实际上它的递归函数就是一个搜索函数,可以说与递归的思想毫无关系。
通常我们遇到的括号匹配如果遇到有不匹配的右括号(之前没有左括号供其匹配我们就直接退出判断函数),但看给出示例的第二行可以看到是接着往后判断的,优先从左括号开始。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pi;
const int N = 2e5 + 10;
const int MOD = 1e9 + 7;
#define endl '\n'
#define PY puts("Yes")
#define PN puts("No")
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
string s;
while (cin >> s)
{
cout << s << endl; //按题目要求输出原字符串
stack<int> stk;
bool valid[101]; //标记数组判断要输出的字符
memset(valid, false, sizeof(valid));
for (int i = 0; i < s.length(); i++)
{
if (s[i] == '(') //遇到左括号进栈
stk.push(i);
else if (s[i] == ')')
{
if (stk.empty()) //如果栈是空的说明这个不合法标记后跳过
{
valid[i] = true;
continue;
}
else //将上一个左括号出栈
stk.pop();
}
}
while (!stk.empty()) //判断左括号没有右括号匹配的情况
{
valid[stk.top()] = true;
stk.pop();
}
for (int i = 0; i < s.length(); i++)
{
if (valid[i]) //根据是左括号还是右括号输出
{
if (s[i] == '(')
cout << "$";
else if (s[i] == ')')
cout << "?";
}
else
cout << " ";
}
cout << endl;
}
return 0;
}