Check if vector of strings has matching brackets
Comments

You have overwhelming amount of comments. It looks to be too much. Usually code should document itself by having good names and intuitive behavior. Intuitive behavior would be one of standard library, for example. Other candidate is int type. In the extreme case you should write why the code does what it does, not what it does.

Implementation

It is really hard to understand what your code does, since it's not straightforward. Code should aim at correctness first, clarity second, performance third.

It's good that you're using range loops.

   if (type.first == c){  //if it's an opening bracket, add a new open bracket to the vector
                incr = 1;
                counts[c].push_back(0);
                break;
            }
            if (type.second == c){  //if it's a closing bracket, set incr to decrement each value
                incr = -1;
                break;
            }


This place of the code is very confusing. In the beginning I thought that we could use else to chain this, but then I noticed that it's type.first and type.second, which changed my opinion. But then I found that it always compares to c, so now it's pretty clear that there have to be else, since second shouldn't be checked if first condition is met. It is good both clarity and performance wise.

        int incr; 


outside loop. It should be inside, because it's logical scope belongs to the loop. If you worry about performance, compiler should be able to figure that out, so your code will be both readable and performant.

Your braces function violate single responsibility principle. The principle greatly improves the code if used correctly.

Names are ambiguous in some places.

So lets make the code better.

Suggested implementation

First of all, lets nail down the name of the "entry point" function. is_valid_brace_sequence in my opinion is alright. 

std::vector&lt;std::string&gt; is_valid_brace_sequence(const std::vector&lt;std::string&gt;&amp; input)


Notice const std::vector&lt;std::string&gt;&amp;. Algorithm doesn't need a copy. Copying will probably decrease performance. 

If it wouldn't be part of problem statement, I would suggest having 2 input iterators for the beginning and end of the input, and one output iterator for the beginning of the output, so algorithm wouldn't mess with allocations.

Next, the algorithm goes over input, calls checker function on every element and records the results:

std::vector&lt;std::string&gt; results;
results.reserve(input.size());
for (const auto&amp; element : input)
{
    bool result = check_validity(element);
    if (result)
    {
        results.push_back("YES");
    }
    else
    {
        results.push_back("NO");
    }
}

return results;


Using reserve increases performance, since vector won't need to resize. Also, it should be used in places where the size of the input in elements is known before hand.

Next, is check_validity function. It will also preserve const correctness:

bool check_validity(const std::string&amp; input)


The algorithm used will be the following: if either left sided brace is encountered ('(', '[','{'), right sided brace will be put into stack. If right sided brace is encountered, top of the stack is checked for the exactly same brace, if it's not, return false. 

bool check_validity(const std::string&amp; input)
{
    std::stack&lt;char&gt; sequence;
    for (const auto&amp; character: input)
    {
        switch (character)
        {
        case '(':
            sequence.push(')');
            break;
        case '{':
            sequence.push('}');
            break;
        case '[':
            sequence.push(']');
            break;
        case ')':
            if (!is_expected_brace(sequence, character))
            {
                return false;
            }
            break;
        case '}':
            if (!is_expected_brace(sequence, character))
            {
                return false;
            }
            break;
        case ']':
            if (!is_expected_brace(sequence, character))
            {
                return false;
            }
            break;
        default:
            continue;       
        }
    }

    return true;
}


So the reason the algorithm works is that stack is LIFO container (last in first out). Since the type of the right sided brace should match the last left sided, so stack matches needs of the algorithm perfectly. Notice the use of switch. It increases performance because it generates jump table. 

I've put all the boilerplate code of checking on encounter of right sided brace into the separate function:

bool is_expected_brace(std::stack&lt;char&gt;&amp; sequence, char brace)
{
    if (sequence.empty() || sequence.top() != brace)
    {
        return false;
    }
    sequence.pop();
    return true;
}


Notice the logical OR operator (||). It provides short circuit ifs, so accessing the stack won't be undefined behavior.

Although it increases readability of the caller function, both of them has tight coupling between each other, so it limits the usability of them in case they are separated.

Put together

#include &lt;vector&gt;
#include &lt;stack&gt;
#include &lt;string&gt;
#include &lt;iostream&gt;

bool is_expected_brace(std::stack&lt;char&gt;&amp; sequence, char brace)
{
    if (sequence.empty() || sequence.top() != brace)
    {
        return false;
    }
    sequence.pop();
    return true;
}

bool check_validity(const std::string&amp; input)
{
    std::stack&lt;char&gt; sequence;
    for (const auto&amp; character: input)
    {
        switch (character)
        {
        case '(':
            sequence.push(')');
            break;
        case '{':
            sequence.push('}');
            break;
        case '[':
            sequence.push(']');
            break;
        case ')':
            if (!is_expected_brace(sequence, character))
            {
                return false;
            }
            break;
        case '}':
            if (!is_expected_brace(sequence, character))
            {
                return false;
            }
            break;
        case ']':
            if (!is_expected_brace(sequence, character))
            {
                return false;
            }
            break;
        default:
            continue;       
        }
    }

    return true;
}

std::vector&lt;std::string&gt; is_valid_brace_sequence(const std::vector&lt;std::string&gt;&amp; input)
{
    std::vector&lt;std::string&gt; results;
    results.reserve(input.size());
    for (const auto&amp; element : input)
    {
        bool result = check_validity(element);
        if (result)
        {
            results.push_back("YES");
        }
        else
        {
            results.push_back("NO");
        }
    }

    return results;
}

int main()
{
    std::vector&lt;std::string&gt; test_input{ "{{}}", "[[[]]", "[](){}", "[[])", "{[()]}" };
    std::vector&lt;std::string&gt; results = is_valid_brace_sequence(test_input);
    for (const auto&amp; element : results)
    {
        std::cout &lt;&lt; element &lt;&lt; " ";
    }

}