【?】【7007】栈、模拟

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;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7632051.html