问题 H(1158): 剔除多余括号
时间限制: 1 Sec 内存限制: 64 MB题目描述
输入一个含有括号的四则运算表达式,要求去掉可能含有的多余的括号,结果要保持原表达式中变量和运算符的相对位置不变,且与原表达式等价
,
不要求化简。另外不考虑
'+' '-'
用作正负号的情况,即输入表达式不会出现
(+a)
或
(-a)
的情形。
输入
第1行:一个字符串表示要整理的表达式
输出
第1行:整理后的结果
样例输入
((a+b)*f)-(i/j)
样例输出
(a+b)*f-i/j
要求处理输入字符串,首先,对于任意的表达式,我们都可以找的一个最后运算的运算符op,op左、右侧的表达式必定可以分别处理,于是我们采用二分的方法。
先把要处理的表达式左右括号全部删掉,再通过括号内与括号外的运算优先级判断该括号是否必须存在,如果必须,就还原括号。
至于如何判断运算优先级,就要看最后运算的运算符op,即断点的优先级。
设左区间的断点为op1,右区间的断点为op2,当前区间为op
则(A op1 B)op (C op2 D)中
if(优先级(op1)< 优先级(op))
还原左区间括号;
if(优先级(op)> 优先级(op2))
还原右区间括号;
if(op为 ' - ' 或 ' / ')特别处理;
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; #define MAXN 100000 #define MAXM #define INF 0x3f3f3f3f #define LL long long char A[MAXN+10]; int find_another(int x)//查询前括号 { int cnt=0; for(int i=x;;--i) { if(A[i]==')') ++cnt; else if(A[i]=='(') --cnt; if(!cnt)return i; } } int find_breakpoint(int l,int r)//查询当前区间断点 { int pos=0; for(int i=r;i>=l;--i) { if(A[i]==')')//跳过高优先级区间 i=find_another(i); else if((A[i]=='*'||A[i]=='/')&&!pos)//次一级断点 pos=i; else if(A[i]=='+'||A[i]=='-')//运算级最低,必为断点 return i; } return pos; } void dfs(int l,int r,char &op)//二分处理字符串 { while(A[r]==')'&&find_another(r)==l)//删除当前区间两端括号 { A[l]=A[r]=0; ++l,--r; } if(l>=r) { op=0; return; } int pos=find_breakpoint(l,r); char op1,op2; dfs(l,pos-1,op1); dfs(pos+1,r,op2); op=A[pos]; if((op1=='-'||op1=='+')&&(op=='*'||op=='/')) A[l]='(',A[pos-1]=')'; if((op=='/'&&op2)||((op=='-'||op=='*')&&(op2=='+'||op2=='-'))) A[pos+1]='(',A[r]=')'; } int main() { gets(A+1); int len=strlen(A+1); char op; dfs(1,len,op); for(int i=1;i<=len;++i) if(A[i])printf("%c",A[i]); puts(""); }