/* Topcoder SRM 686, D1, 250-pointer: BracketSequenceDiv1 * James S. Plank * Tue Oct 11 00:57:32 EDT 2016 */ #include #include #include #include #include #include #include #include #include #include using namespace std; class BracketSequenceDiv1 { public: map Cache; long long count(string s); }; long long BracketSequenceDiv1::count(string s) { int i; long long one; long long b, e; map ::iterator mit; /* Base case -- empty string equals 0 */ if (s.size() == 0) 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; }