分析
首先找到方程式的左右等式,分别统计左右等式中所有元素的出现次数,然后对比是否左右两边个元素个数相同。
将每个元素分割出来,统计其中的元素个数。
用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;
}
想问下大佬 为什么每次co都是co=co*stoi(temp.substr(0, k)); 为什么不直接co=stoi(temp.substr(0, k));? 这是有什么说法嘛?
%%%