第十八次CCF计算机软件能力认证 化学方程式 (模拟+哈希表)

本文介绍了一种使用C++实现的化学方程式解析算法。该算法通过深度优先搜索(DFS)来统计化学方程式中各元素的出现次数,并判断方程式的左右两边是否平衡。通过构建哈希表来存储每种元素的计数,从而实现了对方程式的有效解析。

分析

首先找到方程式的左右等式,分别统计左右等式中所有元素的出现次数,然后对比是否左右两边个元素个数相同。
将每个元素分割出来,统计其中的元素个数。
用dfs统计括号中元素的具体个数。

C++ 代码

#include<bits/stdc++.h>
using namespace std;
typedef unordered_map<string,int> msi;  //定义一个哈希表,表示每个元素的出现个数
string s;
int n;
msi dfs(string& s,int& u)
{
    msi res;
    while(u<s.size())
    {
        if(s[u]=='(')   //左括号就进行dfs,统计括号内元素个数
        {
            u++;
            auto t=dfs(s,u);    
            u++;
            int co=1,k=u;
            while(k<s.size() && isdigit(s[k])) k++; //统计后缀出现次数 例如(OH)2中的2
            if(k>u)
            {
                co=co*stoi(s.substr(u,k-u));    //计算出现的次数具体是多少
                u=k;
            }
            for(auto x:t)   //将该括号中的所有元素次数都加上co次
                res[x.first]+=x.second*co;
        }
        else if(s[u]==')') break;   //右括号直接返回
        else{
            int j=u+1;  //妙用,因为元素是一个大写或者一个大写加一个小写字母
            while(j<s.size() && s[j]>='a' && s[j]<='z') j++;    //此处只用判断是否是小写即可
            auto t=s.substr(u,j-u); //得到该元素
            u=j;
            int co=1;
            while(j<s.size() && isdigit(s[j])) j++; //统计该元素后缀出现次数 例如Ca2的2
            if(j>u) 
            {
                co=co*stoi(s.substr(u,j-u));
                u=j;
            }
            res[t]+=co; //该元素出现次数+co
        }
    }
    return res;
}
msi jdg(string s)   //得到哈希表
{
    msi res;
    for(int i=0;i<s.size();i++)
    {
        int j=i+1;
        while(j<s.size() && s[j]!='+') j++; //将每个元素分割出来
        string temp=s.substr(i,j-i);    //得到单个化合物的表达式 如2NaOH,Ca(OH)2
        i=j;
        int co=1,k=0;   
        while(k<temp.size() && isdigit(temp[k])) k++; //得到该元素前缀的次数如2NaOH的2
        if(k) co=co*stoi(temp.substr(0, k));
        // cout<<co<<" ";
        auto d=dfs(temp,k); //通过dfs得到该化合物各个元素出现个数
        for(auto x:d)   //将d中每个字符出现次数都加上co
            res[x.first]+=x.second*co;
    }
    return res;
}
int main()
{
    cin>>n;
    getline(cin,s);
    while(n--)
    {
        getline(cin,s);
        int idx=s.find('=');        //找到等号进而找到左右两部分
        auto l=jdg(s.substr(0,idx)),r=jdg(s.substr(idx+1)); //统计左右两边的元素个数
        if(l==r) puts("Y"); //如果两个哈希表相同,则输出Y
        else puts("N");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jay_fearless

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值