1.普通匹配
表达式括号匹配1
题目描述
假设一个表达式有英文字母(小写)、运算符(+,—,*,/)和左右小(圆)括号构成,以“@”作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返回“YES”;否则返回“NO”。表达式长度小于255,左圆括号少于20个。
输入描述
一行表达式。
输出描述
“YES” 或“NO”
样例
输入
2*(x+y)/(1-x)@
输出
YES
思路
用栈进行匹配,遇见'('入栈
遇见')'出栈,下溢时做出错处理
若没有出错且栈为空,匹配成功
代码实现
#include<bits/stdc++.h>
using namespace std;
int main(){
//初始化
stack<char>s;
string t;
int f=1;
cin>>t;
//遍历输入字符串所有字符
for(int i=0;i<t.size();i++){
if(t[i]=='@') break;//结束符
else if(t[i]=='(') s.push(t[i]);//入栈
else if(t[i]==')'){
if(s.empty()) {//若为空做出错处理
f=0;break;
}
else s.pop();//出栈
}
}
if(f&&s.empty()) cout<<"YES";//没有出错且栈为空
else cout<<"NO";
return 0;
}
练习一下~
表达式括号匹配2
题目描述
假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序任意,如([]())或[([][])]等为正确的匹配,[(])或([]()或(()))均为错误的匹配。
现在的问题是,要求检验一个给定的表达式中的括弧是否正确匹配?
输入一个只包含圆括号和方括号的字符串,判断字符串中的括号是否匹配,匹配就输出“OK”,不匹配就输出“Wrong”。
输入描述
输入一行字符(字符个数小于255)。
输出描述
数据匹配就输出“OK”,不匹配就输出“Wrong”。
样例
输入
[(])
输出
Wrong
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
//初始化
stack<char>s;
string t;
cin>>t;
int f=1;
for(int i=0;i<t.size();i++){
//入栈
if(t[i]=='[') s.push(t[i]);
if(t[i]=='(') s.push(t[i]);
if(t[i]==']'){
if(s.empty()){//若为空做出错处理
f=0;
break;
}
//出栈至有括号配对
while(s.top()!='['){
if(s.empty()){//若为空做出错处理
f=0;
break;
}
s.pop();
}
if(s.empty()){//若为空做出错处理
f=0;
break;
}
s.pop();
}
if(t[i]==')'){
if(s.empty()){//若为空做出错处理
f=0;
break;
}
//出栈至有括号配对
while(s.top()!='('){
if(s.empty()){//若为空做出错处理
f=0;
break;
}
s.pop();
}
if(s.empty()){//若为空做出错处理
f=0;
break;
}
s.pop();
}
}
if(f==1&&s.empty()) cout<<"OK";//没有出错且栈为空
else cout<<"Wrong";
return 0;
}
2.运行崩溃调试
表达式括号匹配3
题目描述
给你一串字符,不超过50个字符,可能包括括号、数字、字母、标点符号、空格,你的任务是检查这一串字符中的( ) ,[ ],{ }是否匹配。
输入描述
每次输入一个字符串,字符串长度不超过50
输出描述
如果匹配就输出“yes”,不匹配输出“no”
样例
输入
sin(20+10)
输出
yes
初试
如果按刚刚的操作去处理,得到如下代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
stack<char>s;
string t;
int f=1;
getline(cin,t);//有空格!!!!
for(int i=0;i<t.size();i++){
if(t[i]=='['||t[i]=='('||t[i]=='{') s.push(t[i]);
if(t[i]==')'){
while(s.top()!='('){
if(s.empty()){
f=0;
break;
}
s.pop();
}
if(s.empty()){
f=0;
break;
}
s.pop();
}
if(t[i]==']'){
while(s.top()!='['){
if(s.empty()){
f=0;
break;
}
s.pop();
}
if(s.empty()){
f=0;
break;
}
s.pop();
}
if(t[i]=='}'){
while(s.top()!='{'){
if(s.empty()){
f=0;
break;
}
s.pop();
}
if(s.empty()){
f=0;
break;
}
s.pop();
}
}
if(f&&s.empty()) cout<<"yes";
else cout<<"no";
return 0;
}
然后……
运行崩溃 (60%)
为什么会这样?
分析与调试
看这段代码:
while(s.top()!='('){
if(s.empty()){
f=0;
break;
}
s.pop();
}
用while时复杂度提高,所以导致出错
分析:括回左边只要有不匹配的括号,就是无法匹配
所以直接判断左边括号是否匹配即可
经过分析后,上面的代码可以修改成:
if(s.top()=='(') s.pop();//匹配
else{
f=0;
break;//否则无法匹配
}
修改后代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
stack<char>s;
string t;
int f=1;
getline(cin,t);//有空格!!!!
for(int i=0;t[i];i++){
if(t[i]=='['||t[i]=='('||t[i]=='{') s.push(t[i]);
if(t[i]==')'){
if(s.top()=='(') s.pop();//匹配
else{
f=0;
break;//否则无法匹配
}
}
if(t[i]==']'){
if(s.top()=='[') s.pop();//匹配
else{
f=0;
break;//否则无法匹配
}
}
if(t[i]=='}'){
if(s.top()=='{') s.pop();//匹配
else{
f=0;
break;//否则无法匹配
}
}
}
if(f&&s.empty()) cout<<"yes";
else cout<<"no";
return 0;
}
呃好像……
运行崩溃 (60%)
为了进一步防止 运行崩溃 (60%) ,我们可以用数组代替栈,top为头指针
#include<bits/stdc++.h>
using namespace std;
int main(){
char stack[55];
char t[55];
int f=1,top=0;
fgets(t,55,stdin);
for(int i=0;t[i];i++){
if(t[i]=='['||t[i]=='('||t[i]=='{') stack[top++]=t[i];
if(t[i]==')'){
if(stack[top-1]=='(') top--;
else{
f=0;
break;
}
}
if(t[i]==']'){
if(stack[top-1]=='[') top--;
else{
f=0;
break;
}
}
if(t[i]=='}'){
if(stack[top-1]=='{') top--;
else{
f=0;
break;
}
}
}
if(f&&top==0) cout<<"yes";
else cout<<"no";
return 0;
}
结果:正确
3.顺序匹配
字符串匹配问题
题目描述
字符串中只含有括号 ()
,[]
,<>
,{}
判断输入的字符串中括号是否匹配。如果括号有互相包含的形式,从内到外必须是 <>
,()
,[]
,{}
,例如。输入: [()]
输出YES
,而输入 ([])
,([)]
都应该输出 NO
。
输入描述
文件的第一行为一个整数nn,表示以下有多少个由括好组成的字符串。接下来的nn行,每行都是一个由括号组成的长度不超过255的字符串。
输出描述
在输出文件中有nn行,每行都是YES或NO。
样例
输入
注:为清晰样例添加了空格
5
{ }{ }< >< >( )( )[ ][ ]
{ { } }{ { } }< < > > < < > > ( ( ) ) ( ( ) ) [ [ ] ] [ [ ] ]
{ { } } { { } } < < > > < < > > ( ( ) ) ( ( ) ) [ [ ] ] [ [ ] ]
{ < > } { [ ] } < < < > > < < > > > ( ( < > ) ) ( ( ) ) [ [ ( < > ) ] ] [ [ ] ]
> < } { { [ ] } < < < > > < < > > > ( ( < > ) ) ( ( ) ) [ [ ( < > ) ] ] [ [ ] ]
输出
YES
YES
YES
YES
NO
基本代码
就是在上一题基础上添了顺序嘛
把顺序先放一边,做其他处理
排序思路与实现
其实很简单,因为只有左括号,只要判断前面的括号嵌套是否正确即可
可以使用整数栈操作
#include<bits/stdc++.h>
using namespace std;
bool stackst(char t[]){
stack<int>s;
for(int i=0;i<strlen(t);i++){
int num=0;
switch(t[i]){
case '<':
s.push(4);
break;
case '(':
if(s.empty()) s.push(3);
else{
num=s.top();
if(num>3) return 0;
s.push(3);
} break;
case '[':
if(s.empty()) s.push(2);
else{
num=s.top();
if(num>2) return 0;
s.push(2);
} break;
case '{':
if(s.empty()) s.push(1);
else{
num=s.top();
if(num>1) return 0;
s.push(1);
} break;
case '>':
if(s.empty()) return 0;
num=s.top();
if(num!=4) return 0;
s.pop();
break;
case ')':
if(s.empty()) return 0;
num=s.top();
if(num!=3) return 0;
s.pop();
break;
case ']':
if(s.empty()) return 0;
num=s.top();
if(num!=2) return 0;
s.pop();
break;
case '}':
if(s.empty()) return 0;
num=s.top();
if(num!=1) return 0;
s.pop();
break;
}
}
if(s.empty()) return 1;
return 0;
}
int main(){
int N;
cin>>N;
while(N){
char t[300];
cin>>t;
if(stackst(t)) cout<<"YES"<<'\n';
else cout<<"NO"<<'\n';
N--;
}
return 0;
}