Kattis Challenge - Animal Classification I'm new to competitive programming and C++ in general.  I have solved the Kattis Animal Classification challenge.  We are given two classification trees, each represented using nested parentheses.  For example, ((3,(1,(5,2))),4) and (((5,1),(2,3)),4) represent the trees

   ╱╲                   ╱╲
  ╱╲ 4                 ╱╲ 4
 ╱ ╱╲                 ╱  ╲
3 1 ╱╲               ╱╲  ╱╲
   5  2             5 1  2 3


The challenge is to report the fact that there are 7 subgroups in common between the two trees (namely {1}, {2}, {3}, {4}, {5}, {1,2,3,5}, and {1,2,3,4,5}).

My approach is to parse the input string [ e.g. ((3,(1,(5,2))),4) ] into a list [ ((3(1(52)))4) ]. After that I note all elements, split it into the two subtrees and add both back to a queue, starting over again, until there is nothing to split anymore. Afterwards i compare the two sets i obtained this way. If i am not mistaken this should lead to a complexity of O(N log(N)), since for every subtree, i need to collect all elements that belong to it, which would amount to N log(N) in a complete binary tree. This works for the provided test sets, but exceeds the time limit on the submission. 

Could you please help me figure out where I can improve my code and what I did inefficiently?

#include &lt;iostream&gt;
#include &lt;list&gt;
#include &lt;algorithm&gt;
#include &lt;string&gt;
#include &lt;unordered_set&gt;
#include &lt;deque&gt;

using namespace std; 


struct hash_X{
  size_t operator()(const unordered_set&lt;int&gt; &amp;x) const{
    int sum = 0;
    for(int i: x){sum = sum+i;}
    return sum;
  }
};

unordered_set&lt;unordered_set&lt;int&gt;, hash_X&gt; mt(list&lt;string&gt; L){
    unordered_set&lt;unordered_set&lt;int&gt;, hash_X&gt; S;
    list&lt;string&gt; K;
    deque&lt;list&lt;string&gt;&gt; Q;
    Q.push_back(L);
    while(not Q.empty()){
    K = Q.back();
    unordered_set&lt;int&gt; tmp;
    for(string s: K){if( s!="(" and s!=")" ){int i = stoi(s); tmp.insert(i);}}
    S.insert(tmp);
    //K is of the form for example (x(yz)), so first we unwrap ~ x(yz) and split into the two subtrees x and (yz)
    //and add both to the queue. If only one node is left ( x ) we dont add it back to the queue
    if(K.size() &gt;= 2){
        K.pop_front();
        K.pop_back();
        list&lt;string&gt;::iterator it = K.begin();
        if(*it == "("){
            int i = 1;
            while(i != 0){
                it++;
                if(*it == ")"){i = i-1;}
                else if(*it == "("){i=i+1;}
                }
            }
        it++;
        list&lt;string&gt; B;
        list&lt;string&gt;::iterator itB = B.begin();
        B.splice(itB, K, it, K.end());
        Q.push_front(K);
        Q.push_front(B);
    }
    Q.pop_back();
    }
    return S;
}


int main(){
    int n;
    string x, y;
    char c;
    list&lt;string&gt; A, B;
    cin &gt;&gt; n;
    cin.ignore();
    cin &gt;&gt; x; 
    cin &gt;&gt; y;
    // parse "((3,(1,(5,2))),4)" into ((3(1(52)))4)
    for(int i = 0; i &lt; x.size(); i++){
    string c = "";
    c += x[i];
    if( c == "(" or c == ")" ){A.push_back(c);}
    if( isdigit(x[i]) ){
        string tmp = "";
        while( isdigit(x[i]) ){
            tmp += x[i];
            i++;
        }
        i--;
        A.push_back(tmp);
    }
    }
    for(int i = 0; i &lt;= y.size(); i++){
    string c = "";
    c += y[i];
    if( c == "(" or c == ")" ){B.push_back(c);}
    if( isdigit(y[i]) ){
        string tmp = "";
        while( isdigit(y[i]) ){
            tmp += y[i];
            i++;
        }
        i--;
        B.push_back(tmp);
    }
    }

    // make the trees
    unordered_set&lt;unordered_set&lt;int&gt;, hash_X&gt; t1 = mt(A);
    unordered_set&lt;unordered_set&lt;int&gt;, hash_X&gt; t2 = mt(B);
    unordered_set&lt;unordered_set&lt;int&gt;, hash_X&gt; i(t1.begin(), t1.end());
    int res = count_if(t2.begin(), t2.end(), [&amp;](unordered_set&lt;int&gt; k) {return i.find(k) != i.end();});
    cout &lt;&lt; res;
}
This isn't really what you're looking for, just some general feedback on your code.  I find the code quite difficult to follow, resolving some of the issues below to help with readability might make it more likely that you will get feedback that aimed at your algorithm.

Naming

Your names seem overly concise.  A few extra letters won't make any difference to the speed of your application, but make it a lot more readable.  Variables in main are n,x,y,c,A,B,i,c,tmp,t1,t2,res.  Without looking at the context, these names are meaningless.

Your mt method is similarly nondescript.  Perhaps make_tree might be more appropriate?

Consistent expecatations

In main, you reuse the variable name i for both an int and an unordered_set&lt;unordered_set&lt;int&gt;, hash_X&gt;.  Switching variable types like this makes your code harder to follow than necessary and illustrates that you could benefit from more meaningful names.

Indentation

Your indentation is all over the place.  This makes it difficult to read.  Sometimes you have indentations next to each nesting level, sometimes you don't.  If it looks like this in your development environment, you should fix it.  If it doesn't, then you need to check the preview when adding code to questions.  Usually copying the whole thing from your IDE, selecting it and clicking the {} icon will format the code correctly.

Consider this:

if(*it == "("){
    int i = 1;
    while(i != 0){
        it++;
        if(*it == ")"){i = i-1;}
        else if(*it == "("){i=i+1;}
        }
    }


At first glance, the final closing brace belongs to the while loop, not the if statement.  This is unnecessarily confusing.

Don't be afraid of using an extra line

Consider the following line or two:

for(string s: K){if( s!="(" and s!=")" ){int i = stoi(s); tmp.insert(i);}}


There's a lot going on there for a single line.  It's a lot easier to read spread across multiple lines:

for(string s: K) {
    if( s!="(" and s!=")" ) {
        int i = stoi(s); 
        tmp.insert(i);
    }
}