Preliminaries for Benelux Algorithm Programming Contest 2019 - B Bracket Sequence(手写栈)

题目链接

Two great friends, Eddie John and Kris Cross, are attending the Brackets Are Perfection Conference. They wholeheartedly agree with the main message of the conference and they are delighted with all the new things they learn about brackets. One of these things is a bracket sequence. If you want to do a computation with + and ×, you usually write it like so: (2×(2+1+0+1)×1)+3+2. The brackets are only used to group multiplications and additions together. This means that you can remove all the operators,as long as you remember that addition isused for numbers outside any parentheses! A bracket sequence can then be shortened to (2(2101)1)32. That is much better, because it saves on writing all those operators. Reading bracket sequences is easy, too. Suppose you have the following bracket sequence 5 2 ( 3 1 ( 2 2 ) ( 3 3 ) 1 ) . You start with addition, so this is the same as the following: 5+2+ ( 3 1 ( 2 2 ) ( 3 3 ) 1 ) . You know the parentheses group a multiplication, so this is equal to 5+2+(3×1×(2 2)×(3 3)×1). Then there is another level of parentheses: that groups an operation within a multiplication, so the operation must be addition. 5+2+(3×1×(2+2)×(3+3)×1)=5+2+(3×1×4×6×1)=5+2+72=79. Since bracket sequences are so much easier than normal expressions with operators, it should be easy to evaluate some big ones. We will even allow you to write a program to do it for you. Note that () is not avalid bracket sequence, nor a subsequence of any valid bracket sequence.

Input
• One line containing a single integer 1≤ n ≤3·105.
• One line consisting of n tokens, each being either (, ), or an integer 0 ≤ x < 109 +7. It is guaranteed that the tokens form a bracket sequence.

Output
the value of the given bracket sequence. Since this may be very large, you should print it modulo 109+7.
在这里插入图片描述
1.题目大意:类似数字表达式的求值,给出的表达式只有数字和括号,最外面的都是加法,第一层括号里是乘法,第二层括号里是加法,然后又是乘法…以此类推,求最后的值并对1e9+7取模

2.第一次写的栈,但是只用两个栈一个表示乘法一个表示加法太难写了。但如果每次都申请一个栈,又觉得会内存溢出。后来想到了递归——也就是找到第一个括号就传到另一个求乘法的函数里,再碰到括号就传到求加法的函数里,但是这样的话需要先输入整个字符串,中间还有很多将单个数字字符连起来的过程,结果超时了

3.正确解法是,使用链式的手写栈,创建3e5个栈,每一对括号都用一个新的栈,记录当前栈的数量,奇数的栈存乘法,偶数的栈存加法,最后每遇到’)'就将当前栈的数作加法或乘法,并将结果存入前一个栈,即当前栈顶数量自减。真的非常巧妙,值得学习!

代码:

#include <iostream>
#include <sstream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=3e5+100;
const int Mod=1e9+7;

struct node{
    int val;
    node *next;
    node(int w,node *t){
        val=w;
        next=t;
    }
};

struct Stack{
    int num;
    node *head;

    Stack(){
        num=0;
        head=nullptr;
    }

    node* push(int val){
        head=new node(val,head);
        num++;
        return head;
    }

    void pop(){
        if(empty()) return;
        node *t=head;
        head=head->next;
        num--;
        delete t;
    }

    int top(){
        if(!empty()) return head->val;
        return 0;
    }

    int size(){
        return num;
    }

    bool empty(){
        return !num;
    }
}st[maxn];



ll getNum(char *s){
    ll ans=0;
    for(int i=0;i<strlen(s);i++){
        ans=ans*10+s[i]-'0';
    }
    return ans;
}


int main(){
    char s[15];
    int n,cnt=0;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%s",s);
        if(s[0]=='(') cnt++;
        else if(s[0]==')'){
            if(cnt&1){
                ll ans=1;
                while(st[cnt].size()){
                    ans=(ans*st[cnt].top())%Mod;
                    st[cnt].pop();
                }
                cnt--;
                st[cnt].push(ans);
            }else{
                ll ans=0;
                while(st[cnt].size()){
                    ans=(ans+st[cnt].top())%Mod;
                    st[cnt].pop();
                }
                cnt--;
                st[cnt].push(ans);
            }

        }else{
            st[cnt].push(getNum(s));
        }
    }
    ll ans=0;
    while(st[0].size()){
        ans=(ans+st[0].top())%Mod;
        st[0].pop();
    }
    printf("%lld\n",ans);
    return 0;
}

/*
//TLE!!!
#include <iostream>
#include <stack>
#include <string>
#include <sstream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int Mod=1e9+7;
string s;
ll getMul(int l,int r);

ll getNum(string str){
    stringstream ss(str);
    ll ans;
    ss>>ans;
    return ans%Mod;
}

ll getSum(int l,int r){
    ll ans=0;
    string num="";
    for(int i=l;i<=r;i++){
        if(isdigit(s[i])) num+=s[i];
        if(s[i]==' '){
            if(num.size()>0) ans=(ans+getNum(num))%Mod;
            num="";
        }
        if(s[i]=='('){
            int flag=1,j=i+1;
            while(flag){
                if(s[j]=='(') flag++;
                if(s[j]==')') flag--;
                if(flag){
                    j++;
                }
            }
            ans=(ans+getMul(i+1,j-1))%Mod;
            i=j;
        }
    }
    return ans;
}

ll getMul(int l,int r){
    ll ans=1LL;
    string num="";
    for(int i=l;i<=r;i++){
        if(isdigit(s[i])) num+=s[i];
        if(s[i]=='('){
            int flag=1,j=i+1;
            while(flag){
                if(s[j]=='(') flag++;
                if(s[j]==')') flag--;
                if(flag){
                    j++;
                }
            }
            ans=(ans*getSum(i+1,j-1))%Mod;
            i=j;
        }
        if(s[i]==' '){
            if(num.size()>0) ans=(ans*getNum(num))%Mod;
            num="";
        }
    }
    return ans;
}

ll solve(){
    int flag=0;
    ll ans=0;
    string num="";
    for(int i=0;i<s.size();i++){
        if(isdigit(s[i])) num+=s[i];
        if(s[i]==' '){
            if(num.size()>0) ans=(ans+getNum(num))%Mod;
            num="";
        }
        if(s[i]=='('){
            int flag=1,j=i+1;
            while(flag){
                if(s[j]=='(') flag++;
                else if(s[j]==')') flag--;
                if(flag){
                    j++;
                }
            }
            ans=(ans+getMul(i+1,j-1))%Mod;
            i=j;
        }
    }
    if(num.size()>0) ans=(ans+getNum(num))%Mod;
    return ans;
}

int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int n;
    cin>>n;
    cin.ignore();
    getline(cin,s);
    cout<<solve();
    return 0;
}
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值