726.cc 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #include <map>
  2. #include <string>
  3. #include <vector>
  4. #include <iostream>
  5. using std::map;
  6. using std::string;
  7. using std::vector;
  8. using std::cout; using std::endl;
  9. class Solution {
  10. public:
  11. string countOfAtoms(string formula) {
  12. map<string, int> atoms = parse_formula(formula);
  13. string result = "";
  14. for (auto& it : atoms) {
  15. result += it.first;
  16. if (1 < it.second)
  17. result += std::to_string(it.second);
  18. }
  19. return result;
  20. }
  21. private:
  22. enum Symbol {UPPER, LOWER, DIGIT, LPARENT, RPARENT, END, ILLEGAL};
  23. struct Token {
  24. string tok;
  25. bool simple;
  26. int cnt;
  27. };
  28. Symbol symbol_of(char ch) {
  29. if ('A' <= ch && ch <= 'Z')
  30. return UPPER;
  31. if ('a' <= ch && ch <= 'z')
  32. return LOWER;
  33. if ('0' <= ch && ch <= '9')
  34. return DIGIT;
  35. if (ch == '(')
  36. return LPARENT;
  37. if (ch == ')')
  38. return RPARENT;
  39. return ILLEGAL;
  40. }
  41. vector<Token> tokenize(string formula) {
  42. vector<Token> result;
  43. int n = formula.size();
  44. for (int i = 0; i < n;) {
  45. switch (symbol_of(formula[i])) {
  46. case UPPER: {
  47. string tok = read_tok(formula, i);
  48. int cnt = read_cnt(formula, i);
  49. result.push_back(Token{tok, true, cnt});
  50. break;
  51. }
  52. case LPARENT: {
  53. string tok = read_formula(formula, i);
  54. int cnt = read_cnt(formula, i);
  55. result.push_back(Token{tok, false, cnt});
  56. break;
  57. }
  58. default: // Dead loop if invalid
  59. break;
  60. }
  61. }
  62. return result;
  63. }
  64. string read_tok(string& str, int& i) {
  65. int beg = i++;
  66. if (i != str.size() && symbol_of(str[i]) == LOWER) {
  67. i++;
  68. return str.substr(beg, 2);
  69. }
  70. return str.substr(beg, 1);
  71. }
  72. int read_cnt(string& str, int& i) {
  73. int n = str.size();
  74. if (i == n || symbol_of(str[i]) != DIGIT)
  75. return 1;
  76. int beg = i;
  77. for (; i < n && symbol_of(str[i]) == DIGIT; i++);
  78. return std::stoi(str.substr(beg, i - beg));
  79. }
  80. string read_formula(string& str, int& i) {
  81. int n = str.size();
  82. int beg = ++i;
  83. int stack = 1;
  84. for (; i < n && 0 < stack; i++) {
  85. switch (symbol_of(str[i])) {
  86. case LPARENT:
  87. stack++;
  88. break;
  89. case RPARENT:
  90. stack--;
  91. break;
  92. default:
  93. break;
  94. }
  95. }
  96. string formula = str.substr(beg, i - 1 - beg);
  97. return formula;
  98. }
  99. map<string, int> merge(vector<map<string, int>> forms) {
  100. map<string, int> result;
  101. for (auto& it : forms)
  102. merge(it, result);
  103. return result;
  104. }
  105. map<string, int> merge(map<string, int>& src, map<string, int>& dst) {
  106. for (auto& it : src)
  107. dst[it.first] = dst[it.first] + it.second;
  108. return dst;
  109. }
  110. map<string, int> parse_formula(string& formula) {
  111. vector<Token> tokens = tokenize(formula);
  112. vector<map<string, int>> forms;
  113. map<string, int> simple;
  114. for (auto& it : tokens) {
  115. if (it.simple) {
  116. simple[it.tok] = simple[it.tok] + it.cnt;
  117. continue;
  118. }
  119. map<string, int> comp = parse_formula(it.tok);
  120. for (auto& t : comp)
  121. t.second *= it.cnt;
  122. forms.push_back(comp);
  123. }
  124. forms.push_back(simple);
  125. return merge(forms);
  126. }
  127. void print_tokens(vector<Token>& tokens) {
  128. for (auto& it : tokens)
  129. cout << "{tok:" << it.tok << " sim:" << it.simple << " cnt:" << it.cnt << "}; ";
  130. cout << endl;
  131. }
  132. };
  133. int main() {
  134. Solution* sol = new Solution;
  135. string formula = "H2O";
  136. cout << sol->countOfAtoms(formula) << endl;
  137. formula = "H2O2((C(H2O)H)12)10";
  138. cout << sol->countOfAtoms(formula) << endl;
  139. formula = "K4(ON(SO3)2)2";
  140. cout << sol->countOfAtoms(formula) << endl;
  141. return 0;
  142. }