基本思路:
一个复杂的化学式:
6A3(BC)4((DE)8((FG)7(HI)5)6)7
开头"6"为整个化学式的系数
去掉整体系数后,整体加上"()",使化学式变为一个大"项"
(A3(BC)4((DE)8((FG)7(HI)5)6)7)
简单处理后的化学式,可以用"项"的形式进行分析
每一项的基本形式:
1、A3 或者 (BC)4,每个大写字母代表一个元素符号,
每个元素符号的组成:一个大写字母,或者大写字母开头,后面
紧跟一个小写字母。
2、每一项的后面紧跟该项的系数
化学式这个大"项"可以看作一棵大树,内部的每个"()"代表子树,子树的
系数为"()"后面紧跟的数字。据此可以分析该化学式。
分析时,从后往前扫描,先扫描计算项的系数,遇到")"后,再递归扫描该项。
每个元素的系数,为递归进入元素所在的"简单项"时,系数的累乘
#include<iostream>
#include<sstream>
#include<string>
#include<map>
#include<cstdio>
using namespace std;
map <string,int> mp[2];
int dfs(string item,int pos,int coef,int i)//返回:分析该item,最后返回item的前一个位置
//pos进入后为子项")"的前一个位置,出为子项"("前一个位置
{
do
{
int subcoef=0,pow=1;
while(isdigit(item[pos]))
subcoef+=pow*(item[pos]-'0'),pow*=10,pos--;//数字从后往前读
if(!subcoef)subcoef=1;
if(item[pos]==')')//遇到"复子杂项",也就是"(AB)4"形式
pos=dfs(item,pos-1,coef*subcoef,i);//pos为"复杂子项"前一个位置
else//遇到"简单子项",也就是"A4"形式,直接截取出元素A,不需要递归
{
int t=pos;//pos为元素小写尾字母
while(islower(item[t]))t--;//t为元素大写首字母
string element = item.substr(t,pos-t+1);
mp[i][element]+=coef*subcoef;//i为前半部分还是后半部分,系数
pos=t-1;//pos跳到该元素之前,继续分析
}
}while(item[pos]!='(');//遇到"("说明,当前项分析结束,开始回溯
return pos-1;
}
void cal(int i,string formula)//取出化学式开头的整体系数,然后给剩余的部分前后加上(),变成"项"
{
//计算系数
int coef=0;
int pos=0;
while(isdigit(formula[pos]))coef=coef*10+formula[pos]-'0',pos++;//数字从前往后读
if(!coef)coef=1;
//剩余部分前后加上"()"
formula.insert(pos,"(");//pos为第一个不为数字的位置
formula+=')';
dfs(formula,formula.length()-2,coef,i);
}
int main()
{
int n;
cin>>n;
while(n--)
{
string equation;//方程式
cin>>equation;
stringstream ss1 (equation);
string part;//等号前后两部分
int i=0;
while(getline(ss1,part,'='))
{
mp[i].clear();
stringstream ss2(part);
string formula;//化学式
while(getline(ss2,formula,'+'))cal(i,formula);
i++;
}
if(mp[0]==mp[1])cout<<"Y"<<endl;
else cout<<"N"<<endl;
}
}