#include <utility>
#include <set>
#include <iostream>
#include <algorithm>
 
template<class T>
class CompareWords {
public:
    bool operator()(T s1, T s2)
    {
        if (s1.length() == s2.length())
        {
            return ( s1 < s2 );
        }
        else return ( s1.length() < s2.length() );
    }
};
 
    template<class Iterator, class Clumps, class Compare>
    void reduce_clumps( Iterator begin, Iterator end, Clumps&& clumps, Compare&& compare) {
      if (begin==end) return;
      typedef decltype(*begin) value_type;
      std::size_t count = 1;
      Iterator run_end = std::find_if( std::next(begin), end, [&]( value_type v ){
        if (!compare(*begin, v)) {
          ++count;
          return false;
        }
        return true;
      });
      clumps( begin, run_end, count );
      return reduce_clumps( std::move(run_end), std::move(end), std::forward<Clumps>(clumps), std::forward<Compare>(compare) );
    }
 
    int main() {
      typedef std::multiset<std::string> mySet;
      typedef std::multiset<std::string>::iterator mySetItr;
 
      mySet mWords { "A", "A", "B" };
 
      reduce_clumps( mWords.begin(), mWords.end(),
        []( mySetItr run_start, mySetItr run_end, std::size_t count )
        {
          std::cout << "Word \"" << *run_start << "\" occurs " << count << " times\n";
        },
        CompareWords<std::string>{}
      );
    }
				I2luY2x1ZGUgPHV0aWxpdHk+CiNpbmNsdWRlIDxzZXQ+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPGFsZ29yaXRobT4KCnRlbXBsYXRlPGNsYXNzIFQ+CmNsYXNzIENvbXBhcmVXb3JkcyB7CnB1YmxpYzoKICAgIGJvb2wgb3BlcmF0b3IoKShUIHMxLCBUIHMyKQogICAgewogICAgICAgIGlmIChzMS5sZW5ndGgoKSA9PSBzMi5sZW5ndGgoKSkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiAoIHMxIDwgczIgKTsKICAgICAgICB9CiAgICAgICAgZWxzZSByZXR1cm4gKCBzMS5sZW5ndGgoKSA8IHMyLmxlbmd0aCgpICk7CiAgICB9Cn07CgogICAgdGVtcGxhdGU8Y2xhc3MgSXRlcmF0b3IsIGNsYXNzIENsdW1wcywgY2xhc3MgQ29tcGFyZT4KICAgIHZvaWQgcmVkdWNlX2NsdW1wcyggSXRlcmF0b3IgYmVnaW4sIEl0ZXJhdG9yIGVuZCwgQ2x1bXBzJiYgY2x1bXBzLCBDb21wYXJlJiYgY29tcGFyZSkgewogICAgICBpZiAoYmVnaW49PWVuZCkgcmV0dXJuOwogICAgICB0eXBlZGVmIGRlY2x0eXBlKCpiZWdpbikgdmFsdWVfdHlwZTsKICAgICAgc3RkOjpzaXplX3QgY291bnQgPSAxOwogICAgICBJdGVyYXRvciBydW5fZW5kID0gc3RkOjpmaW5kX2lmKCBzdGQ6Om5leHQoYmVnaW4pLCBlbmQsIFsmXSggdmFsdWVfdHlwZSB2ICl7CiAgICAgICAgaWYgKCFjb21wYXJlKCpiZWdpbiwgdikpIHsKICAgICAgICAgICsrY291bnQ7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9KTsKICAgICAgY2x1bXBzKCBiZWdpbiwgcnVuX2VuZCwgY291bnQgKTsKICAgICAgcmV0dXJuIHJlZHVjZV9jbHVtcHMoIHN0ZDo6bW92ZShydW5fZW5kKSwgc3RkOjptb3ZlKGVuZCksIHN0ZDo6Zm9yd2FyZDxDbHVtcHM+KGNsdW1wcyksIHN0ZDo6Zm9yd2FyZDxDb21wYXJlPihjb21wYXJlKSApOwogICAgfQoKICAgIGludCBtYWluKCkgewogICAgICB0eXBlZGVmIHN0ZDo6bXVsdGlzZXQ8c3RkOjpzdHJpbmc+IG15U2V0OwogICAgICB0eXBlZGVmIHN0ZDo6bXVsdGlzZXQ8c3RkOjpzdHJpbmc+OjppdGVyYXRvciBteVNldEl0cjsKCiAgICAgIG15U2V0IG1Xb3JkcyB7ICJBIiwgIkEiLCAiQiIgfTsKCiAgICAgIHJlZHVjZV9jbHVtcHMoIG1Xb3Jkcy5iZWdpbigpLCBtV29yZHMuZW5kKCksCiAgICAgICAgW10oIG15U2V0SXRyIHJ1bl9zdGFydCwgbXlTZXRJdHIgcnVuX2VuZCwgc3RkOjpzaXplX3QgY291bnQgKQogICAgICAgIHsKICAgICAgICAgIHN0ZDo6Y291dCA8PCAiV29yZCBcIiIgPDwgKnJ1bl9zdGFydCA8PCAiXCIgb2NjdXJzICIgPDwgY291bnQgPDwgIiB0aW1lc1xuIjsKICAgICAgICB9LAogICAgICAgIENvbXBhcmVXb3JkczxzdGQ6OnN0cmluZz57fQogICAgICApOwogICAgfQ==