算法总结—表达式

· · 算法·理论

表达式求值

我们可以先处理乘法在处理加法:

由于是 a_i\times a_{i+1} 所以数字要从后往前枚举。

记得取模 10000

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[50005];
char c[50005];
signed main(){
    int cnt=1;
    cin>>a[cnt];
    a[1]%=10000;
    while(cin>>c[cnt]>>a[cnt+1]){
        cnt++;
        a[cnt]%=10000;
    } 
    for(int i=cnt;i>=1;i--){
        if(c[i]=='*'){
            a[i]*=a[i+1];
            a[i]%=10000;
            a[i+1]=0;
        }
    }
    int ans=0;
    for(int i=1;i<=cnt;i++){
        ans+=a[i];
        ans%=10000;
    }
    cout<<ans; 
    return 0;
}

后缀表达式

直接用栈处理即可:

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
stack<int>st;
signed main(){
    string s;
    cin>>s;
    while(s.back()=='@'){
        s.pop_back();
    }
    int len=s.size();
    int num=0;
    for(int i=0;i<len;i++){
        if(s[i]>='0'&&s[i]<='9'){
            num*=10;
            num+=s[i]-'0';
        }else if(s[i]=='.'){
            st.push(num);
            num=0;
        }else{
            int x=st.top();
            st.pop();
            int y=st.top();
            st.pop();
            if(s[i]=='+'){
                st.push(x+y);
            }
            if(s[i]=='-'){
                st.push(y-x);
            }
            if(s[i]=='*'){
                st.push(x*y);
            }
            if(s[i]=='/'){
                st.push(y/x);
            }
        }
    }
    cout<<st.top();
    return 0;
}

中缀表达式值(expr)

这道题的大致思路就是先将中缀表达式转化为后缀,在用后缀表达式求出答案。

具体思路

无解

优先级:

右括号>乘除>加减>左括号

中缀转后缀

用一个字符串 suf 来存储后缀表达式,用一个栈 st 来处理中缀转后缀的过程。

后缀算答案

有了后缀表达式,这道题就和上题一模一样了,后缀算答案直接按上题思路处理即可。

时间复杂度 O(|S|^2)

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
bool is(char c){
    return c=='+'||c=='-'||c=='*'||c=='/';
}
bool check(string s){
    stack<char>st;
    for(auto c:s){
        if(c=='('){
            st.push('(');
        }
        if(c==')'){
            if(st.size()==0){
                return 0;
            }
            st.pop();
        }
    }
    if(st.size()){
        return 0;
    }
    int len=s.size(); 
    for(int i=1;i<len;i++){
        if(is(s[i-1])&&is(s[i])){
            return 0;
        }
    }
    return 1;
}
int prio[205];
stack<char>st;
stack<int>ans;
signed main(){
    string s;
    cin>>s;
    if(check(s)==0){
        cout<<"NO";
        return 0;
    }
    while(s.back()=='@'){
        s.pop_back();
    }
    prio['(']=0;
    prio['+']=1;
    prio['-']=1;
    prio['*']=2;
    prio['/']=2;
    int len=s.size();
    string suf="";
    for(int i=0;i<len;i++){
        if(s[i]>='0'&&s[i]<='9'){
            suf+=s[i];
        }else{
            if(s[i]=='('){
                st.push(s[i]);
            }else if(s[i]==')'){
                while(st.size()>1&&st.top()!='('){
                    suf+=st.top();
                    st.pop();
                }
                st.pop();
            }else{
                while(st.size()&&prio[st.top()]>=prio[s[i]]){
                    suf+=st.top();
                    st.pop();
                }
                st.push(s[i]);
            }
        }
    }
    while(st.size()){
        suf+=st.top();
        st.pop();
    }
    len=suf.size();
    for(int i=0;i<len;i++){
        if(suf[i]>='0'&&suf[i]<='9'){
            ans.push(suf[i]-'0');
        }else{
            if(ans.size()<2){
                continue;
            }
            int x=ans.top();
            ans.pop();
            int y=ans.top();
            ans.pop();
            if(suf[i]=='+'){
                ans.push(x+y);
            }
            if(suf[i]=='-'){
                ans.push(y-x);  
            }
            if(suf[i]=='*'){
                ans.push(x*y);  
            }
            if(suf[i]=='/'){
                ans.push(y/x);  
            }
        }
    }
    cout<<ans.top();
    return 0;
}

表达式的转换

这道题的中最转后缀代码与上一道题基本相似,但是要想输出具体过程就不能按照上一题的代码处理了,因为这道题有删除后缀表达式的一部分和插入后缀表达式的一部分,这种插入和删除操作比较快的就是 vector 了。

然后每一轮都直接输出 vecotr 的元素。

代码

#include<bits/stdc++.h>
using namespace std;
struct node{
    bool flag;
    int x;
    char c;
};
vector<node>vec;
int cnt=0;
void add(bool flag,int x,char c){
    cnt++;
    vec.push_back({flag,x,c});
    return;
}
int prio[205];
stack<char>st;
int qpow(int x,int y){
    if(y==0){
        return 1;
    }
    if(y==1){
        return x;
    }
    if(y%2==0){
        int t=qpow(x,y/2);
        return t*t;
    }
    return qpow(x,y-1)*x;
}
int main(){
    string s;
    cin>>s;
    prio['(']=0;
    prio['+']=1;
    prio['-']=1;
    prio['*']=2;
    prio['/']=2;
    prio['^']=3;
    prio[')']=4;
    while(s.back()=='@'){
        s.pop_back();
    }
    int len=s.size();
    for(int i=0;i<len;i++){
        if(s[i]>='0'&&s[i]<='9'){
            add(1,s[i]-'0',' ');
        }else{
            if(s[i]=='('){
                st.push(s[i]);
            }else if(s[i]==')'){
                while(st.size()>1&&st.top()!='('){
                    add(0,-1e9,st.top());
                    st.pop();
                }
                st.pop();
            }else if(s[i]=='^'){
                while(st.size()&&prio[st.top()]>prio[s[i]]){
                    add(0,-1e9,st.top());
                    st.pop();
                }
                st.push(s[i]);
            }else{
                while(st.size()&&prio[st.top()]>=prio[s[i]]){
                    add(0,-1e9,st.top());
                    st.pop();
                }
                st.push(s[i]);
            }
        }
    }
    while(st.size()){
        add(0,-1e9,st.top());
        st.pop();
    }
    for(int i=0;i<cnt;i++){
        if(vec[i].flag==0){
            cout<<vec[i].c;
        }else{
            cout<<vec[i].x;
        }
        cout<<" ";
    }
    cout<<"\n";
    for(int i=0;i<cnt;i++){
        if(vec[i].flag==0){
            int x=vec[i-1].x;
            int y=vec[i-2].x;
            char c=vec[i].c;
            int T=3;
            while(T--){
                vec.erase(vec.begin()+i-2);
            }
            if(c=='+'){
                vec.insert(vec.begin()+i-2,{1,x+y,' '});
            }
            if(c=='-'){
                vec.insert(vec.begin()+i-2,{1,y-x,' '});
            }
            if(c=='*'){
                vec.insert(vec.begin()+i-2,{1,x*y,' '});
            }
            if(c=='/'){
                vec.insert(vec.begin()+i-2,{1,y/x,' '});
            }
            if(c=='^'){
                vec.insert(vec.begin()+i-2,{1,qpow(y,x),' '});
            }
            i=0;
            cnt--;
            cnt--;
            for(int j=0;j<cnt;j++){
                if(vec[j].flag==0){
                    cout<<vec[j].c;
                }else{
                    cout<<vec[j].x;
                }
                cout<<" ";
            }
            cout<<"\n";
        }
    }
    return 0;
}