Time Limit: 10 second
Memory Limit: 2 MB
问题描述
对一个只含单个大写英文字母,”+”,”-“,”(“和”)”的表达式,其中单个大写英文字母表示变量,进行如下处理:去掉表达式中的全部括号,并对”+”,”-“进行相应的变号,最后得到一个与所给表达式等价且长度最短的表达式。
Input
一个字符串,如(-A)-((-B)-(-C))
Output
一个字符串,如-A+B-C(长度为6)
Sample Input
(-A)-((-B)-(-C))
Sample Output
-A+B-C
【题目链接】:http://noi.qz5z.com/viewtask.asp?id=7007
【题解】
输入的时候不能有无意义的嵌套像是(-(-A))什么的;下面这个程序不支持取反操作。。它只会把’-‘当做普通的减法;
然后脱括号则运行得很好;
思路就是遇到一个左括号就入栈;
同时记录这个左括号左边一个字符是什么;
遇到右括号就根据左括号的左边那个字符做相应的事情;
减法的话,把当前处理的这个括号里面的加法变成减法,减法变成加法就好;去掉括号就好;
【完整代码】
#include <cstdio>
#include <iostream>
#include <string>
#include <stack>
using namespace std;
string s1;
stack <int> a;
int main()
{
//freopen("F:\rush.txt","r",stdin);
cin >> s1;
s1 = " ("+s1+')';
int len = s1.size()-1;
int i = 1;
while (i <= len)
{
if (s1[i] == '(')
{
a.push(i-1);
i++;
}
else
if (s1[i] == ')')
{
s1.erase(i,1);
switch (s1[a.top()])
{
case '(':
s1.erase(a.top()+1,1),i--;
break;
case '+':
{
if (s1[a.top()+2] == '-')
s1.erase(a.top(),2),i-=2;
else
s1.erase(a.top()+1,1),i--;
break;
}
case '-':
{
for (int j = a.top()+2;j <= i-1;j++) //把当前处理的这个括号内的符号变一下
{
if (s1[j] == '-')
s1[j] = '+';
else
if (s1[j] == '+')
s1[j] = '-';
}
if (s1[a.top()+2] == '+')//如果这个括号右边一个字符原来是-号变成正号了前面那个符号就删掉;
s1.erase(a.top(),2),i-=2;
else
s1.erase(a.top()+1,1),i--;
//如果这个括号右边一个字符是数字;说明是一个正数,前面那个负号刚好保留,表示这个数变成负数,括号里面的符号上面已经变过了;
break;
}
}
a.pop();
}
else
i++;
len = s1.size()-1;
}
s1.erase(0,2);
cout << s1<<endl;
return 0;
}