表达式求值
表达式求值常常是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:
因为数读入完了,所以我们需要处理一下。如果栈顶此时是乘号,那弹出栈顶,把新栈顶变为新栈顶乘输入完的数。这样,右括号处理时就只需要加减法了。
不是乘号,直接放入栈中。
之后(代码里可以搞清楚),清空存储数的东西。
情况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);
}
-完结撒花-