#include #include #include #include #include #include #include #include #include #include #include using namespace std; class Solution { public: unordered_map Cache; long long count(const string &s); }; long long Solution::count(const string &s) { int i; long long one; long long b, e; /* Base case -- empty string equals 0 */ if (s.size() <= 1) return 0; /* Memoization looks at the cache first. */ if (Cache.find(s) != Cache.end()) return Cache[s]; /* Set one to be the answer when you erase the first character. If the first character is a closing brace, that's all you can do, so return the answer in that case. */ one = count(s.substr(1)); if (s[0] == ')' || s[0] == ']') { Cache[s] = one; return one; } /* Otherwise, for each closing brace/parenthesis that matches the first character, split the string in two at that point, and recurse on the first half and the second half, adding one to account for empty strings. Add in the products. */ for (i = 1; i < s.size(); i++) { if ((s[0] == '(' && s[i] == ')') || (s[0] == '[' && s[i] == ']')) { b = count(s.substr(1, i-1))+1; e = count(s.substr(i+1))+1; one += (b*e); } } /* At the end, put the value into the cache, and return. */ Cache[s] = one; return one; } int main() { Solution sol; string s; cin >> s; cout << sol.count(s) << endl; return 0; }