您好,欢迎来到百家汽车网。
搜索
您的当前位置:首页CCF-CSP认证考试准备第十四天 201912-3 化学方程式

CCF-CSP认证考试准备第十四天 201912-3 化学方程式

来源:百家汽车网


### Day14:1.201912-3

#### 1.201912-3:化学方程式(大模拟,字符串解析,嵌套结构处理(括号,用栈))
(1)先获取40分(未处理左右括号)->60分(处理一对括号)->学习满分代码
(2)
##### 1.思路一(不断解析字符串,直到最小单元为化学式,然后来计算):
(1) 对于每个方程式,**`isBalanced`函数将方程式分为左右两部分("="号分割)**,分别调用`parseSide`解析左右两侧的化学式。
(2)**`parseSide`函数负责处理方程式的一侧,它会调用`parseFormula`来解析具体的化学式(“+”号和i<s.size()分割)**。
(3)**`parseFormula`使用栈来处理括号嵌套结构**,通过逐个字符扫描,将化学式中的每个元素及其数量存储到**哈希表**中。
(4) **最后,通过比较左右两边的元素数量**(**比较两个哈希表**),判断是否配平。
(5)代码:
```
#include <bits/stdc++.h>

using namespace std;

//系数字符串转整形,i是引用,自动++
int parseNumber(string s,int &i){
    int sum=0;
    while(i<s.size() && s[i]>='0' && s[i]<='9'){
        sum=sum*10+s[i]-'0';
        i++;
    }
    return sum==0?1:sum;//无系数默认为1(可以变通拓展) 
}

//提取一个的化学式的元素及系数(核心) 
map<string,int> parseFormula(string s,int qianXi){
    map<string,int> res;
    stack<map<string,int>> st; 
    st.push(map<string,int>());//先加一层栈顶 
    for(int i=0;i<s.size();){
        if(s[i]=='('){
            //进入新的一层括号 
            st.push(map<string,int>());
            i++;
        }
        else if(s[i]==')'){
            //提取一个层级的map<string,int>,乘上括号后面的系数 
            i++;
            int kuohaoXi=parseNumber(s,i);//这个函数更改i,下面不用i++了 
            auto top_ele=st.top();//top_ele为map<string,int>和类型 
            st.pop();//弹出这层,下面的 s.top()为上一层 
            for(auto &x:top_ele){//x为pair<string,int>类型 
                st.top()[x.first]+=x.second*kuohaoXi;//改变上一层的<string,int>,加上这一层的<string,int>为这一层每个string的int(下标系数)乘上这一层的括号系数 
            }
        }
        else{//处理这一层括号内的单个元素 
            string ele; 
            ele+=s[i++];//提取大写字母
            while(i<s.size() && s[i]>='a' && s[i]<='z'){
                //提取小写字母 
                ele+=s[i++];
            } 
            int xiaXi=parseNumber(s,i);//提取下标系数
            st.top()[ele]+=xiaXi; 
        }
    }
    //将栈顶的map乘上前面系数放到res的map里面 
    for(auto &x:st.top()){
        res[x.first]+=x.second*qianXi;
    }
    return res;
}

//提取一侧的化学方程式的元素及系数 
map<string,int> parseSide(string s){
    map<string,int> res;
    for(int i=0;i<s.size();){
        int qianXi=parseNumber(s,i);//获取前面系数 
        int start=i;//一个化学式的开始
        while(i<s.size() && s[i]!='+')    i++;//+分隔一个化学式
        auto formula_ele=parseFormula(s.substr(start,i-start),qianXi);//解析一个化学式,获取元素哈希表
        //把每一个化学式哈希表加入一侧方程式哈希表中 
        for(auto x:formula_ele){
            res[x.first]+=x.second;
        }
        i++;//跳过+号 
    }
    return res;
}

//判断左右两个化学方程式是否相等 
bool isBalanced(string s){
    auto pos=s.find('=');//通过"="号划分
    string left=s.substr(0,pos);
    string right=s.substr(pos+1);
    auto left_ele=parseSide(left);//解析一测方程式 
    auto right_ele=parseSide(right);
    return left_ele==right_ele;
}

int main(){
    int n;
    cin>>n;
    while(n--){
        string s;
        cin>>s;
        cout<<(isBalanced(s)?"Y":"N")<<endl;
    }
    return 0;
}
```
(6)栈使用核心(括号嵌套):
1.确定栈的元素,本题为map<string,int>,表示当前括号内的元素和数量
2.初始化栈并添加一个栈顶
3.确定何时压入一个栈元素并相应操作:遇到'('压入一个新的map<string,int>,表示这一个括号内的元素和数量
4.确定何时弹出一个栈元素并相应操作:遇到')'弹出这一个括号内的map<string,int>,获取上一个括号内的map<string,int>(即为top()),加上这一个括号内的元素下标系数乘以算得的括号系数
5.处理一个括号内的栈元素,大写字母+小写字母+小标系数=一个化学式,存入当map<string,int>中
6.最后栈顶元素为这一个方程式的map<string,int>,但不包括前面的系数,所以结果map<string,int>为栈顶的map<string,int>乘上传入的前面系数
```
//提取一个的化学式的元素及系数(核心) 
map<string,int> parseFormula(string s,int qianXi){
    map<string,int> res;
    stack<map<string,int>> st; 
    st.push(map<string,int>());//先加一层栈顶 
    for(int i=0;i<s.size();){
        if(s[i]=='('){
            //进入新的一层括号 
            st.push(map<string,int>());
            i++;
        }
        else if(s[i]==')'){
            //提取一个层级的map<string,int>,乘上括号后面的系数 
            i++;
            int kuohaoXi=parseNumber(s,i);//这个函数更改i,下面不用i++了 
            auto top_ele=st.top();//top_ele为map<string,int>和类型 
            st.pop();//弹出这层,下面的 s.top()为上一层 
            for(auto &x:top_ele){//x为pair<string,int>类型 
                st.top()[x.first]+=x.second*kuohaoXi;//改变上一层的<string,int>,加上这一层的<string,int>为这一层每个string的int(下标系数)乘上这一层的括号系数 
            }
        }
        else{//处理这一层括号内的单个元素 
            string ele; 
            ele+=s[i++];//提取大写字母
            while(i<s.size() && s[i]>='a' && s[i]<='z'){
                //提取小写字母 
                ele+=s[i++];
            } 
            int xiaXi=parseNumber(s,i);//提取下标系数
            st.top()[ele]+=xiaXi; 
        }
    }
    //将栈顶的map乘上前面系数放到res的map里面 
    for(auto &x:st.top()){
        res[x.first]+=x.second*qianXi;
    }
    return res;
}

```

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- baijiahaobaidu.com 版权所有 湘ICP备2023023988号-9

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务