#include <iostream>
#include <unordered_set>
#include <string>
#include <vector>
class RedundantBracketRemover
{
public:
RedundantBracketRemover(const std::string& s)
{
remove_redundant_brackets(s, 0);
}
const std::vector<std::string>& get() const { return m_output; }
private:
void remove_redundant_opening_brackets(const std::string& s, size_t end)
{
int balance = 0;
for (size_t i = end; i--;)
{
if (s[i] == ')')
{
++balance;
}
else if (s[i] == '(' && --balance < 0)
{
char last = 0;
for (size_t j = i; j < s.length(); ++j)
{
if (s[j] == '(' && last != '(')
{
auto s2 = std::string(s).erase(j, 1);
if (m_nodes.insert(s2).second)
remove_redundant_opening_brackets(s2, i);
}
last = s[j];
}
return;
}
}
m_output.push_back(s);
}
void remove_redundant_brackets(const std::string& s, size_t begin)
{
int balance = 0;
for (size_t i = begin; i < s.length(); ++i)
{
if (s[i] == '(')
{
++balance;
}
else if (s[i] == ')' && --balance < 0)
{
char last = 0;
for (size_t j = 0; j <= i; ++j)
{
if (s[j] == ')' && last != ')')
{
auto s2 = std::string(s).erase(j, 1);
if (m_nodes.insert(s2).second)
{
remove_redundant_brackets(s2, i);
}
}
last = s[j];
}
return;
}
}
remove_redundant_opening_brackets(s, s.length());
}
private:
std::vector<std::string> m_output;
std::unordered_set<std::string> m_nodes;
};
std::vector<std::string> remove_redundant_brackets(const std::string& s)
{
return RedundantBracketRemover(s).get();
}
int main()
{
const auto s = "()(())(()())(())((())()))))))()))))(((((()(((((())(()())((())(()()))";
//const auto s = "(a)())()))((b(b)";
auto variants = remove_redundant_brackets(s).size();
std::cout << "variants: " << variants << std::endl;
// for (auto&& s : remove_redundant_brackets(s))
// {
// std::cout << s << std::endl;
// }
}