思路:
就是一道很复杂的模拟题
每个化学元素的数目来源有3种:化合物最前面的数字mul,该元素后面的数字mul2,括号累计得到的数字mul3。
分别维护这三个值即可。
mul和mul2都可以在确定元素的时候算出来
而对于mul3,我们一开始就进行括号匹配,得到每一个左括号对应右括号后面的数字。那么之后遍历序列时,每经过一个左括号,mul3就乘上该左括号对应数目。每经过一次右括号,mul3就除以该括号对应的数目。
题外话:
改来改去都只有90分,最后无奈和别人代码对拍,最后发现还有一个很重要的条件:左右元素数目相同!
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 5e3 + 7;
char s[10005];
map<int,int>dat1,dat2;
char check(char x) {
if(x >= 'a' && x <= 'z') return true;
return false;
}
bool Isnumber(char x) {
return (x >= '0' && x <= '9');
}
void init() {
dat1.clear();dat2.clear();
int n = strlen(s + 1);
stack<pair<int,char> >stk;
for(int i = 1;i <= n;i++) {
if(s[i] == '(') {
stk.push({i,'('});
}
else if(s[i] == ')'){
int pre = stk.top().first;stk.pop();
int num = 0;
while(Isnumber(s[i + 1])) {
num = num * 10 + s[i + 1] - '0';
i++;
}
dat1[pre] = max(num,1);
dat2[i] = max(num,1);
}
}
}
void solve(map<string,int>&mp,int sta,int ed) {
int now = 0,mul = 1,mul3 = 1;
int left = 0;
for(int i = sta;i <= ed;i++) {
if(isalpha(s[i])) {
string now;
now += s[i];
if(check(s[i + 1])) {
i++;
now += s[i];
}
int mul2 = 0;
while(Isnumber(s[i + 1])) {
mul2 = mul2 * 10 + s[i + 1] - '0';
i++;
}
mul2 = max(mul2,1);
mp[now] += mul * mul2 * mul3;
}
else if(Isnumber(s[i])) {
int mul2 = 0;
i--;
while(Isnumber(s[i + 1])) {
mul2 = mul2 * 10 + s[i + 1] - '0';
i++;
}
mul = mul2;
}
else if(s[i] == '(') {
left++;
mul3 *= dat1[i];
}
else if(s[i] == ')') {
left--;
while(Isnumber(s[i + 1])) {
i++;
}
mul3 /= dat2[i];
}
else {
mul = 1;
}
}
}
int main() {
int T;scanf("%d",&T);
while(T--) {
map<string,int>mp1,mp2;
scanf("%s",s + 1);
init();
int pos = 0;
int n = (int)strlen(s + 1);
for(int i = 1;i <= n;i++) {
if(s[i] == '=') {
pos = i;break;
}
}
solve(mp1,1,pos);
solve(mp2,pos + 1,n);
int flag = 1;
if(mp1.size() != mp2.size()) flag = 0;
for(auto &it : mp1) {
string x = it.first;
if(mp1[x] != mp2[x]) {
flag = 0;
break;
}
}
if(flag)printf("Y\n");
else printf("N\n");
}
return 0;
}