邓心一 4 anos atrás
pai
commit
711f04a59b
1 arquivos alterados com 161 adições e 0 exclusões
  1. 161 0
      leetcode/hard/726.cc

+ 161 - 0
leetcode/hard/726.cc

@@ -0,0 +1,161 @@
+#include <map>
+#include <string>
+#include <vector>
+
+#include <iostream>
+
+using std::map;
+using std::string;
+using std::vector;
+
+using std::cout; using std::endl;
+
+class Solution {
+public:
+    string countOfAtoms(string formula) {
+        map<string, int> atoms = parse_formula(formula);
+        string result = "";
+        for (auto& it : atoms) {
+            result += it.first;
+            if (1 < it.second)
+                result += std::to_string(it.second);
+        }
+        return result;
+    }
+private:
+    enum Symbol {UPPER, LOWER, DIGIT, LPARENT, RPARENT, END, ILLEGAL};
+
+    struct Token {
+        string tok;
+        bool simple;
+        int cnt;
+    };
+
+    Symbol symbol_of(char ch) {
+        if ('A' <= ch && ch <= 'Z')
+            return UPPER;
+        if ('a' <= ch && ch <= 'z')
+            return LOWER;
+        if ('0' <= ch && ch <= '9')
+            return DIGIT;
+        if (ch == '(')
+            return LPARENT;
+        if (ch == ')')
+            return RPARENT;
+        return ILLEGAL;
+    }
+
+    vector<Token> tokenize(string formula) {
+        vector<Token> result;
+        int n = formula.size();
+        for (int i = 0; i < n;) {
+            switch (symbol_of(formula[i])) {
+                case UPPER: {
+                    string tok = read_tok(formula, i);
+                    int cnt = read_cnt(formula, i);
+                    result.push_back(Token{tok, true, cnt});
+                    break;
+                }
+                case LPARENT: {
+                    string tok = read_formula(formula, i);
+                    int cnt = read_cnt(formula, i);
+                    result.push_back(Token{tok, false, cnt});
+                    break;
+                }
+                default: // Dead loop if invalid
+                    break;
+            }
+        }
+        return result;
+    }
+
+    string read_tok(string& str, int& i) {
+        int beg = i++;
+        if (i != str.size() && symbol_of(str[i]) == LOWER) {
+            i++;
+            return str.substr(beg, 2);
+        }
+        return str.substr(beg, 1);
+    }
+
+    int read_cnt(string& str, int& i) {
+        int n = str.size();
+        if (i == n || symbol_of(str[i]) != DIGIT)
+            return 1;
+        int beg = i;
+        for (; i < n && symbol_of(str[i]) == DIGIT; i++);
+        return std::stoi(str.substr(beg, i - beg));
+    }
+
+    string read_formula(string& str, int& i) {
+        int n = str.size();
+        int beg = ++i;
+        int stack = 1;
+        for (; i < n && 0 < stack; i++) {
+            switch (symbol_of(str[i])) {
+                case LPARENT:
+                    stack++;
+                    break;
+                case RPARENT:
+                    stack--;
+                    break;
+                default:
+                    break;
+            }
+        }
+        string formula = str.substr(beg, i - 1 - beg);
+        return formula;
+    }
+
+    map<string, int> merge(vector<map<string, int>> forms) {
+        map<string, int> result;
+        for (auto& it : forms)
+            merge(it, result);
+        return result;
+    }
+
+    map<string, int> merge(map<string, int>& src, map<string, int>& dst) {
+        for (auto& it : src)
+            dst[it.first] = dst[it.first] + it.second;
+        return dst;
+    }
+
+    map<string, int> parse_formula(string& formula) {
+        vector<Token> tokens = tokenize(formula);
+        vector<map<string, int>> forms;
+        map<string, int> simple;
+        for (auto& it : tokens) {
+            if (it.simple) {
+                simple[it.tok] = simple[it.tok] + it.cnt;
+                continue;
+            }
+            map<string, int> comp = parse_formula(it.tok);
+            for (auto& t : comp)
+                t.second *= it.cnt;
+            forms.push_back(comp);
+        }
+        forms.push_back(simple);
+        return merge(forms);
+    }
+
+    void print_tokens(vector<Token>& tokens) {
+        for (auto& it : tokens)
+            cout << "{tok:" << it.tok << " sim:" << it.simple << " cnt:" << it.cnt << "}; ";
+        cout << endl;
+    }
+};
+
+int main() {
+    Solution* sol = new Solution;
+
+    string formula = "H2O";
+    cout << sol->countOfAtoms(formula) << endl;
+
+    formula = "H2O2((C(H2O)H)12)10";
+    cout << sol->countOfAtoms(formula) << endl;
+
+    formula = "K4(ON(SO3)2)2";
+    cout << sol->countOfAtoms(formula) << endl;
+
+    return 0;
+}