http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11342 Problem description |
The chemical formula of a molecule M describes its atomic make-up. Chemical formulas obey the following grammar: M := G | M G G := S | S C S := A | '(' M ')' C := T | N E E := D | D E T := '2' | ... | '9' N := '1' | ... | '9' D := '0' | .. | '9' A := U | U L | U L L U := 'A' | .. | 'Z' L := 'a' | .. | 'z' The count C represents a multiplier for the subgroup S that precedes it. For example, H2O has two H (hydrogen) and one O (oxygen) atoms, and (AlC2)3Na4 contains 3 Al (aluminum), 6 C (carbon) and 4 Na (sodium) atoms. |
Input |
The input will contain data for one or more test cases. For each test case, there will be one line of input, containing a valid chemical formula. Each line will have no more than 100 characters. |
Output |
For each line of input there will be one line of output which is the atomic decomposition of the chemical in the form of a sum as shown in the sample output. The atoms are listed in lexicographical order, and a count of 1 is implied and not explicitly written. There are no blank spaces in the output. All of the counts in the correct output will be representable in 32-bit signed integers. |
Sample Input |
H2O (AlC2)3Na4 |
Sample Output |
2H+O 3Al+6C+4Na |
Problem Source |
2012 Rocky Mountain Regional Contest 题意:按字典序升序输出所有元素 思路:一道恶心的模拟题啊,暴力模拟即可,弄了好久啊,一开始是全部算出来在进行叠加,但是超时了,于是就每次计算完一个元素后都放进去,终于过了,0ms #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; struct node { char word[105]; int cnt; } a[105]; char str[105]; int cmp(node x,node y) { return strcmp(x.word,y.word)<0; } int main() { while(~scanf("%s",str)) { int len = strlen(str),flag = 1; int l = -1,ll = 0; int i,j,k,zuo,t; for(i = 0; i<=100; i++) memset(a[i].word,' ',sizeof(a[i].word)); for(i = 0; i<len; i++) { if(str[i]>='A' && str[i]<='Z') { if(l!=-1) a[l].word[ll] = ' '; flag = 1; ll = 0; if(l!=-1) { int tt = 0,c; for(j = k; j<len; j++)//从该元素往后走,找括号 { if(str[j] == '(')//找左括号 tt++; else if(str[j] == ')') { if(tt)//与左括号匹配,消去一个无用的右括号 tt--; else { zuo--;//匹配包含该元素的左括号 j++; c = 0; while(str[j]>='0' && str[j]<='9')//计算括号后面的数字 { c = c*10+str[j]-'0'; j++; } j--; if(c)//非0则与原来的数字相乘 a[l].cnt*=c; } } if(!zuo)//没有包含该元素的左括号则跳出 break; } } for(j = 0; j<l; j++) { if(!strcmp(a[j].word,a[l].word))//有与该元素匹配的就直接将该元素的数目累加,并且长度减1,没有则不管 { a[j].cnt+=a[l].cnt; l--; break; } } l++;//下一个元素 a[l].word[ll++] = str[i];//放进结构体 k = i;//记录位置 a[l].cnt = 1;//初始化个数为1 t = zuo = 0; for(j = i; j>=0; j--)//记录左边将此元素包裹在内的左括号的数量 { if(str[j] == ')') t++; else if(str[j] == '(') { if(t) t--; else zuo++; } } } else if(str[i]>='a' && str[i]<='z') a[l].word[ll++] = str[i]; else if(str[i]>='0' && str[i]<='9' && flag && (str[i-1]>='A' && str[i-1]<='Z' || str[i-1]>='a' && str[i-1]<='z') ) {//这条件很重要,这是计算紧跟在元素后的数字,但不能算括号后面的数字 flag = 0; int c = 0; while(str[i]>='0' && str[i]<='9') { c = c*10+str[i]-'0'; i++; } i--; if(c) a[l].cnt*=c; } } while(zuo)//这是计算最后一个元素,因为最后一个元素可能没有算 { int tt = 0,c; for(j = k; j<len; j++) { if(str[j] == '(') tt++; else if(str[j] == ')') { if(tt) tt--; else { zuo--; j++; c = 0; while(str[j]>='0' && str[j]<='9') { c = c*10+str[j]-'0'; j++; } j--; if(c) a[l].cnt*=c; } } } } for(j = 0; j<l; j++) {//医务室计算最后一个元素 if(!strcmp(a[j].word,a[l].word)) { a[j].cnt+=a[l].cnt; l--; break; } } sort(a,a+l+1,cmp); if(a[0].cnt!=1) printf("%d%s",a[0].cnt,a[0].word); else printf("%s",a[0].word); for(i = 1; i<=l; i++) { if(a[i].cnt!=1) printf("+%d%s",a[i].cnt,a[i].word); else printf("+%s",a[i].word); } printf(" "); } return 0; }
|