题目描述

时间限制:500ms 内存限制:256.0MB

问题描述

   给定一个只包含加(\(+\))、减(\(-\))、乘(\(*\))三种运算的\(n\)个字符的合法表达式,请求出该表达式的值对\(2527\)取余后的结果。

输入格式

   第二行输入一个字符串\(S\),表示一个合法表达式。

输出格式

   输出一个整数,表示该表达式的值对\(2527\)取余后的结果。

样例输入1

 (26*3*8)+(1*11)-(9*15*9)

样例输出1

 1947

样例输入2

 (510*510+208)-(511*511-813)

样例输出2

 0

数据规模和约定

   \(1\leq |S|\leq 5×10^6\),其中\(|S|\)为字符串\(S\)的长度。
   保证表达式仅包含数字、左右括号、加号、减号、乘号,且表达式中的数字均为整数且\(\in [0, 2527)\)

提示

   请使用较快的读入方式。

解析

   可以利用中缀表达式转后缀表达式的方法在计算。转化过程可以运用栈。

转化:

   \(s1[top]\) 用字符串模拟出栈的效果,方便存储后缀表达式,\(top\)为栈顶。
   \(s2\) 用于临时存贮运算符。
   \(str\) 用于存储中缀表达式。
   按顺序依次遍历\(str_i(0\leq i\leq len)\)。若为操作数,则直接入栈\(s1\);若为左括号\((\),则直接入栈\(s2\);若为右括号\(')'\),则栈\(s2\)将左括号\((\)以上的所有运算符一次出栈并入栈\(s1\);若为运算符,则当栈\(s2\)栈顶元素为括号或者栈顶元素运算优先级比\(str_i\)低时或者栈为空时直接入栈,否则依次出栈并入栈到\(s1\)中,直到栈顶元素满足要求为止,再将\(str_i\)入栈\(s2\)
   最终将栈\(s2\)中剩余元素依次出栈并入栈到\(s1\)中。
   得出后缀表达式。

求值:

   \(st\) \(int\)类型栈,用于存储操作数。
   按顺序依次遍历栈\(s1_i(0\leq i\leq len)\)。若\(isdigit(s1_i)\),则找到\(j\)并满足\(!isdigit(s1_{j+1})\),将操作数记下并压入栈\(st\)中;若为运算符,则将栈\(st\)弹出两个数并作出相应的运算,再将结果压入栈\(st\)中。
   栈\(st\)的栈顶元素即为该表达式的运算值。

#include <iostream>
#include <stack>
#include <cctype>
#include <string>
using namespace std;
const int mod = 2527;
stack<char> s2;
string str, s1 = "";
int priority(char symb) {
	if (symb == '(' || symb == ')') return 0;
	if (symb == '+' || symb == '-') return 1;
	return 2;
}
int calc(int a, int b, char symb) {
	if (symb == '+') return a + b;
	else if (symb == '-') return a - b;
	else return a * b;
}
string Infix_to_Suffix() {
	int str_len = str.length();
	while (!s2.empty()) s2.pop();
	for (int i = 0; i < str_len; i++) {
		if (str[i] >= '0' && str[i] <= '9') {
			s1 += str[i];
			if (!(str[i + 1] >= '0' && str[i + 1] <= '9')) s1 += '.';
		} else if (str[i] == '(') s2.push(str[i]);
		else if (str[i] == ')') {
			while (s2.top() != '(')
				s1 += s2.top(), s2.pop();
			s2.pop();
		} else {
			while (!s2.empty() && priority(str[i]) <= priority((char)s2.top()))
				s1 += s2.top(), s2.pop();
			s2.push(str[i]);
		}
	}
	while (!s2.empty())
		s1 += s2.top(), s2.pop();
	return s1;
}
int cnt(string s1) {
	stack<int> st;
	int s1_len = s1.length(), ans = 0;
	while (!st.empty()) st.pop();
	for (int i = 0, temp; i < s1_len; i++) {
		if (s1[i] == '.') continue;
		if (isdigit(s1[i])) {
			temp = 0;
			while (s1[i] >= '0' && s1[i] <= '9') temp = temp * 10 + (s1[i++] - '0');
			st.push(temp % mod);
		} else {
			int a = st.top(); st.pop();
			int b = st.top(); st.pop();
			st.push(calc(b, a, s1[i]) % mod); //注意运算顺序和取模
		}		
	}
	return (st.top() + mod) % mod; //经过数学运算取模最终结果不能为负数
}
int main(int argc, char** argv) {
	cin >> str;
	cout << cnt(Infix_to_Suffix()) << endl;
	return 0;
}

-end-

相关文章: