给出一个字符串格式的化学分子式,计算原子的个数
每个化学元素都是由一个大写字母,或者一个大写字母后跟着若干个小写字母组成,例如H是一个化学元素,Mg也是一个化学元素。
每个分子式中,原子的个数写在元素后面,如果原子个数是1,那么原子个数省略。例如H2O和H2O2都是有效的分子式,但H1O2不是有效分子式。
每个分子式中包含若干括号,为简单起见,分子式中只有小括号。
每次输入一个分子式,对每个给定的分子式,求出每个原子的个数,按照原子字母表的顺序排列,并输出。
一行,一个字符串表示输入的分子式
按要求输出答案
H2O
H2O
Mg(OH)2
H2MgO2
K4(ON(SO3)2)2
K4N2O14S4
"""
若为元素名加个数,则直接求解元素名及其原子个数,更新到字典中;
若包含括号,对括号内表达式递归求解。
"""
def get_digit(s): # 求从s[0]开始的数字,若没有数字返回1,并返回数字的位数
k = 0
while k < len(s) and s[k].isdigit():
k += 1
num = 1 if k == 0 else int(s[:k])
return num, k
def fun(s, dic, buff): # buff为化学分子式s括号外的加成
t, n = 0, len(s) # t从0到n对s遍历
while t < n:
if s[t].isupper(): # 若为大写字母,则求元素名对应的个数
j = t + 1
while j < n and s[j].islower():
j += 1
num, tmp = get_digit(s[j:]) # 得到表达式所示的个数
if s[t:j] not in dic:
dic[s[t:j]] = 0
dic[s[t:j]] += num * buff # num*buff
t = j + tmp
elif s[t] == '(': # 括号情况,对括号内表达式递归
stack = ['(']
j = t + 1
while stack: # 找到与外层括号配对的右括号下标j-1
if s[j] == '(':
stack.append('(')
elif s[j] == ')':
stack.pop()
j += 1
num, tmp = get_digit(s[j:])
fun(s[t + 1:j - 1], dic, num * buff) # 对括号内s[t + 1:j - 1]表达式递归求解
t = j + tmp
if __name__ == "__main__":
s = input().strip() # 化学分子式
dic = {} # 存储化学原子及其个数
fun(s, dic, 1) # 构造dic
ans = "" # 排序并按要求输出
for i in sorted(list(dic.keys())):
ans += i
if dic[i] > 1:
ans += str(dic[i])
print(ans)
#include <bits/stdc++.h>
using namespace std;
int main(){
string s, t="", r="";
cin>>s;
deque<int> Q;
vector<string> S;
vector<int> v;
int l=s.length(), m=1, cnt=0, k=0;
for(int i=l-1;i>=0;i--){
if(isdigit(s[i]))
t = s[i] + t;
else{
if(t!=""){
Q.push_front(stoi(t));
m *= stoi(t);
cnt++;
t = "";
}
if(islower(s[i]))
r = s[i] + r;
else if(isupper(s[i])){
S.push_back(s[i]+r);
v.push_back(m);
if(cnt>k){
if(m!=1){
m /= Q.front();
Q.pop_front();
}
cnt--;
}
r = "";
}else{
if(s[i]==')')
k++;
else if(s[i]=='('){
if(m!=1){
m /= Q.front();
Q.pop_front();
}
cnt--;
k--;
}
}
}
}
map<string, int> M;
for(int i=0;i<S.size();i++)
M[S[i]] += v[i];
for(map<string,int>::iterator it=M.begin();it!=M.end();it++){
if(it->second==1)
cout<<it->first;
else
cout<<it->first<<it->second;
}
cout<<endl;
return 0;
} import java.util.*;
// 栈 + Map计数
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.next();
char[] c = s.toCharArray();
Deque<Map<String, Integer>> stack = new LinkedList<>();
int n = c.length;
for (int i = 0; i < n;) {
if (Character.isUpperCase(c[i])) {
int j = i + 1;
while (j < n && Character.isLowerCase(c[j])) j++;
String key = s.substring(i, j);
int num = 0;
while (j < n && Character.isDigit(c[j])) {
num = num * 10 + c[j] - '0';
j++;
}
i = j;
num = num == 0 ? 1 : num;
Map<String, Integer> map = new HashMap<>();
map.put(key, num);
stack.push(map);
} else if (c[i] == '(') {
Map<String, Integer> map = new HashMap<>();
map.put("(", -1);
stack.push(map);
i++;
} else { // 遇到 ) 要合并 () 里面的并找到与之匹配的 (
int num = 0, j = i + 1;
while (j < n && Character.isDigit(c[j])) {
num = num * 10 + c[j] - '0';
j++;
}
i = j;
num = num == 0 ? 1 : num;
Map<String, Integer> map = new HashMap<>();
while (!stack.peek().containsKey("(")) {
Map<String, Integer> mp = stack.pop();
for (String key : mp.keySet()) {
map.merge(key, mp.get(key) * num, Integer::sum);
}
}
stack.pop();
stack.push(map);
}
}
Map<String, Integer> map = new HashMap<>(); // 合并栈内剩余的
while (!stack.isEmpty()) {
Map<String, Integer> mp = stack.pop();
for (String key : mp.keySet()) {
map.merge(key, mp.get(key), Integer::sum);
}
}
List<String> list = new ArrayList<>(map.keySet()); // 字典序
Collections.sort(list);
StringBuilder sb = new StringBuilder();
for (String key : list) {
sb.append(key);
int val = map.get(key);
if (val > 1) sb.append(val);
}
System.out.println(sb.toString());
}
} class MainActivity:
def main(self):
# Read the data
s = input()
# Get the results
results = self.__traverse(s)
# Construct the result
results = sorted(list(results.items()), key=lambda x: x[0])
results = list(map(lambda x: '%s%d' % (x[0], x[1]) if x[1] > 1 else x[0], results))
result = ''.join(results)
print(result)
def __traverse(self, s):
# Initialization
results = dict()
cnt = 0
elementCache = []
ptr = 0
# Traverse
while ptr < len(s):
char = s[ptr]
if ord('A') <= ord(char) <= ord('Z'):
if cnt and elementCache:
element = ''.join(elementCache)
if cnt > 1:
cnt = int(str(cnt)[1:])
results[element] = results.get(element, 0) + cnt
cnt = 1
elementCache = [char]
ptr += 1
elif ord('a') <= ord(char) <= ord('z'):
elementCache.append(char)
ptr += 1
elif char.isnumeric():
cnt = cnt * 10 + int(char)
ptr += 1
else: # (
# Add the cache first
if cnt and elementCache:
element = ''.join(elementCache)
if cnt > 1:
cnt = int(str(cnt)[1:])
results[element] = results.get(element, 0) + cnt
elementCache = []
cnt = 1
# Cope with the content in the bracket
bracketCnt = 1
cacheS = []
ptr += 1
while bracketCnt:
cacheS.append(s[ptr])
if bracketCnt and s[ptr] == ')':
bracketCnt -= 1
elif s[ptr] == '(':
bracketCnt += 1
ptr += 1
cacheS.pop() # Remove the outer ')'
subS = ''.join(cacheS)
subResult = self.__traverse(subS)
while ptr < len(s) and s[ptr].isnumeric():
cnt = cnt * 10 + int(s[ptr])
ptr += 1
if cnt > 1:
cnt = int(str(cnt)[1:])
for element, times in subResult.items():
results[element] = results.get(element, 0) + times * cnt
if cnt:
element = ''.join(elementCache)
if cnt and element:
if cnt > 1:
cnt = int(str(cnt)[1:])
results[element] = results.get(element, 0) + cnt
return results
if __name__ == '__main__':
M = MainActivity()
M.main() #include <iostream> #include <stack> #include <string> #include <map> using namespace std; string countOfAtoms(string formula) { string res = ""; stack<map<string, int> > st; map<string, int> cur; int n = formula.size(), pos = 0; while (pos < n) { if (formula[pos] == '(') //遇到“(”压栈, 清空当前cur { ++pos; st.push(cur); cur.clear(); } else if(formula[pos] == ')') //出栈“)”出栈, { int i = ++pos; while (pos < n && isdigit(formula[pos])) //统计“)”后的数字 { ++pos; } int multiple = stoi(formula.substr(i, pos - i)); //for (auto a : cur) //{ // st.top()[a.first] += a.second * multiple; //在当前栈顶,添加新元素 //} //cur = st.top(); //st.pop(); map<string, int> preCur = st.top(); //此时preCur保存了上一时刻的元素 st.pop(); for (auto a : cur) //合并当前cur的元素到preCur { preCur[a.first] += a.second*multiple; } cur = preCur; } else { int i = pos++; while (pos < n && islower(formula[pos])) //识别元素 { pos++; } string elem = formula.substr(i, pos - i); i = pos; while (pos < n && isdigit(formula[pos])) //识别元素后面的数字 { ++pos; } string cnt = formula.substr(i, pos - i); cur[elem] += cnt.empty() ? 1 : stoi(cnt); //当前元素存入cur } } for (auto a : cur) { res += a.first + (a.second == 1 ? "" : to_string(a.second)); } return res; } int main() { string formula, result; cin >> formula; result = countOfAtoms(formula); cout << result << endl; }
#include<bits/stdc++.h>
using namespace std;
int main()
{
// 原子格式 大写的单个字符
// 或者双字符 第一个大写 第二个小写
string s;
vector<char>v;
string tmp = "";
while(cin>>s)
{
for(int i=0;i<s.size();++i)
{
if(s[i]=='(') v.push_back('#');
else if(s[i]==')'){
while(v.back()!='#')
{
tmp = v.back()+tmp;
v.pop_back();
}
v.pop_back();
}
else if((s[i]<='Z'&&s[i]>='A')||(s[i]>='a'&&s[i]<='z'))
v.push_back(s[i]);
else{
int cnt = 0;
string last = "";
if(s[i-1]>='A'&&s[i-1]<='Z') last += s[i-1];
else {
last = last + s[i-1];
last = s[i-2] + last;
}
while(i<s.size()&&s[i]>='0'&&s[i]<='9')
{
cnt = cnt*10 + (s[i]-'0');
++i;
}
if(tmp!=""){
while(cnt--)
{
for(char c:tmp)
v.push_back(c);
}
}
else{
cnt-=1;
while(cnt--)
{
for(char c:last)
v.push_back(c);
}
}
//for(char t:v)
// cout<<t;
//cout<<endl;
tmp.clear();
--i;
}
}
}
map<string,int>mp;
while(!v.empty())
{
string tmp = "";
char c = v.back();
v.pop_back();
if(c>='A'&&c<='Z') tmp += c;
else {
tmp+=c;
tmp = v.back()+tmp;
v.pop_back();
}
mp[tmp] += 1;
}
for(auto it=mp.begin();it!=mp.end();++it)
{
if(it->second>1)
cout<<it->first<<it->second;
else cout<<it->first;
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
struct node{
string s;
int num;
node (string s, int num){
this->s = s;
this->num = num;
}
};
string int_to_string(int i){
string res;
stringstream ss;
ss << i;
ss >> res;
return res;
}
int main() {
string s;
map<string, int> mp;
map<string, string> decode;
vector <string> st;
vector <string> tu;
vector <node> ret;
cin >> s;
for (int i = 0; i < s.length(); i++){
string ans = "";
string str = "";
if(s[i] >= 'A' && s[i] <= 'Z'){
ans += (int_to_string(i));
str.push_back(s[i]);
while((i + 1) < s.length() && s[i + 1] >= 'a' && s[i + 1] <= 'z'){
i++;
str.push_back(s[i]);
}
if((i + 1) < s.length()){
if(s[i + 1] >= '0' && s[i + 1] <= '9'){
int bar = 0;
while((i + 1) < s.length() && s[i + 1] >= '0' && s[i + 1] <= '9'){
i++;
bar = bar * 10 + (s[i] - '0');
}
mp[ans] = bar;
} else {
mp[ans] = 1;
}
} else {
mp[ans] = 1;
}
decode[ans] = str;
st.push_back(ans);
//cerr << "ans == " << ans << endl;
//cerr << "str == " << str << endl;
} else if(s[i] == '('){
string cur = "(";
st.push_back(cur);
} else if(s[i] == ')'){
int foo;
if((i + 1) < s.length() && s[i + 1] >= '0' && s[i + 1] <= '9'){
foo = 0;
while((i + 1) < s.length() && s[i + 1] >= '0' && s[i + 1] <= '9'){
i++;
foo = 10 * foo + (s[i] - '0');
}
} else {
foo = 1;
}
//cerr << "foo == " << foo << endl;
while(!st.empty()){
string use = st.back();
// cerr << "use == " << use << endl;
// cerr << "str == " << decode[use] << endl;
if(use == "("){
st.pop_back();
break;
}
mp[use] *= foo;
tu.push_back(use);
st.pop_back();
}
while(!tu.empty()){
st.push_back(tu.back());
tu.pop_back();
}
}
}
for (int i = 0; i < st.size(); i++){
//cerr << decode[st[i]] << endl;
ret.push_back(node(decode[st[i]], mp[st[i]]));
}
sort(ret.begin(), ret.end(), [&](node a, node b){return a.s < b.s;});
for (int i = 0; i < (int)ret.size(); i++){
int num = ret[i].num;
if((i + 1) < (int)ret.size() && ret[i].s == ret[i + 1].s){
while((i + 1) < ret.size() && ret[i].s == ret[i + 1].s){
i++;
num += ret[i].num;
}
}
cout << ret[i].s;
if(num > 1){
cout << num;
}
}
cout << "\n";
return 0;
} import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @Auther:srd-czk
* @Date:2019/9/7
* @Description:a2019
* @version:1.0
*/
public class Main {
private static String toString(int i) {
StringBuilder sb = new StringBuilder();
sb.append((char)('A' + i / 27));
if (i % 27 != 0) sb.append((char)('a' + i % 27 - 1));
return sb.toString();
}
private static int[] process(char[] chs, int i, int j) {
int[] res = new int[26 * 27];
while (i < j + 1) {
if (chs[i] >= 'A' && chs[i] <= 'Z') {
char c = chs[i];
if (i + 1 < j + 1 && chs[i + 1] >= 'a' && chs[i + 1] <= 'z') {
i++;
int k = (c - 'A') * 27 + 1 + (chs[i] - 'a');
if (i + 1 < j + 1 && Character.isDigit(chs[i + 1])) {
int p = 0;
i++;
while (i < j + 1 && Character.isDigit(chs[i])) {
p = p * 10 + chs[i++] - '0';
}
res[k] += p;
} else {
res[k]++;
i++;
}
} else if (i + 1 < j + 1 && Character.isDigit(chs[i + 1])) {
int p = 0;
i++;
while (i < j + 1 && Character.isDigit(chs[i])) {
p = p * 10 + chs[i++] - '0';
}
res[27 * (c - 'A')] += p;
} else {
res[27 * (c - 'A')]++;
i++;
}
} else {
int cnt = 1;
int start = ++i;
while (i < j + 1 && cnt != 0) {
if (chs[i] == '(') cnt++;
else if (chs[i] == ')') cnt--;
i++;
}
int[] sub = process(chs, start, i - 2);
int p = chs[i++] - '0';
while (i < j + 1 && Character.isDigit(chs[i])) {
p = p * 10 + chs[i++] - '0';
}
for (int k = 0; k < sub.length; k++) {
res[k] += sub[k] * p;
}
}
}
return res;
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String s = bf.readLine();
int[] res = process(s.toCharArray(), 0, s.length() - 1);
for (int i = 0; i < res.length; i++) {
if (res[i] > 0) {
System.out.print(toString(i));
if (res[i] > 1) System.out.print(res[i]);
}
}
System.out.println();
bf.close();
}
}