1. 程式人生 > 其它 >表示式求值-中綴轉字首表示式

表示式求值-中綴轉字首表示式

題目描述

時間限制: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-