您的位置:首页 > 其它

cqbzoj 1158 剔除多余括号

2016-07-01 16:20 246 查看







问题 H(1158): 剔除多余括号

时间限制: 1 Sec  内存限制: 64 MB


题目描述

输入一个含有括号的四则运算表达式,要求去掉可能含有的多余的括号,结果要保持原表达式中变量和运算符的相对位置不变,且与原表达式等价,不要求化简。另外不考虑'+'
'-'用作正负号的情况,即输入表达式不会出现(+a)或(-a)的情形。
[align=left][/align]
[align=left][/align]


输入

第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("");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: