表达式求值

表达式求值常常是cxy的一大烦恼。总是会出各种错误,究竟该怎么办?今天,我来讲解一下我写的魔鬼版本——栈。

〇、题面

问题描述

给定一个只包含加(+)、减(-)、乘(*)三种运算的\(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\times 10^6\) ,其中\(|S|\)为字符串\(S\)的长度。

保证表达式仅包含数字、左右括号、加号、减号、乘号,且表达式中的数字均为整数且\(\in [0,2527)\)

一、栈思想

我因为过于辣鸡,只好用了一个栈存数与符号。
可是一个栈怎么同时存数与符号呢?机智的我把2528认作+,把2529认作-,把2529认作*,把2529认作(。至于为什么没有),后面再说。
可恶的数据竟然出现了超过2527的数,于是我后面代码里都在前面加了一个2(在此感谢hjy同学的猜测)。

每次对于一个字符,我们分类讨论:

  1. 如果他是数字,加在前面的数字里,继续往后;
  2. 如果是加减乘和右括号,说明数已经输入完毕,进入情况1,然后把数推入栈。(左括号前面肯定有符号)
  3. 如果是加减乘和左括号,就把他们推入栈中。
  4. 右括号进入情况2。

情况1:
因为数读入完了,所以我们需要处理一下。如果栈顶此时是乘号,那弹出栈顶,把新栈顶变为新栈顶乘输入完的数。这样,右括号处理时就只需要加减法了。
不是乘号,直接放入栈中。
之后(代码里可以搞清楚),清空存储数的东西。
情况2:
现在这个括号结束了,经过上面的整合只剩下一堆加减,方便极了。这里贴代码:

if(c==')'){
	n2=0;//n2表示当前数
	while(st.top()!=22531){//22531是左括号
		n2=st.top();//首先获取当前数
		st.pop();//弹掉这个数
		if(st.top()==22529) now-=n2;//减法,即...-XXX...
		else now+=n2;//加法...+XXX...
		now%=2527;//取余
		if(st.top()!=22531) st.pop();//只要没有到结束(要留着)就去掉符号
	}
	st.pop();//去掉左括号
	if(!st.empty()&&st.top()==22530){//非空且是乘号
		st.pop();//弹出乘号
		now*=st.top();//乘上
		now%=2527;//取余
		st.pop();//弹出这个数
	}
	st.push(now);//再把一通计算的结果放进去
	now=0;//恢复出厂设置
	continue;//跳过后面
}

二、代码(无注释)

#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;
stack<int> st;//22528=+,22529=-,22530=*,22531=(
int main(){
	ios::sync_with_stdio(0);
	string s;
	char c;
	cin>>s;
	int l=s.size(),now=0,n2;
	bool get=0;
	st.push(22531);
	s+=')';
	for(int i=0;i<=l;i++){
		c=s[i];
		if(c=='+'||c=='-'||c=='*'||c==')'){
			if(st.top()==22530){
				st.pop();
				now*=st.top();
				now%=2527;
				st.pop();
			}
			if(get) st.push(now);
			now=0;
			get=0;
		}
		if(c=='+') st.push(22528);
		if(c=='-') st.push(22529);
		if(c=='*') st.push(22530);
		if(c=='(') st.push(22531);
		if(c==')'){
			n2=0;
			while(st.top()!=22531){
				n2=st.top();
				st.pop();
				if(st.top()==22529) now-=n2;
				else now+=n2;
				now%=2527;
				if(st.top()!=22531) st.pop();
			}
			st.pop();
			if(!st.empty()&&st.top()==22530){
				st.pop();
				now*=st.top();
				now%=2527;
				st.pop();
			}
			st.push(now);
			now=0;
			continue;
		}
		if(c>='0'&&c<='9'){
			now=now*10+(c-'0');
			get=1;
		}
	}
	cout<<((st.top()%2527)+2527)%2527<<endl;
	int _=0;
	return ~~(0^_^0);
}

-完结撒花-

posted @ 2021-07-30 17:23  cyx001  阅读(144)  评论(0编辑  收藏  举报