#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include <algorithm>
#include <chrono>
#include <sstream>

struct my_string {
    std::string s;
    std::string const* operator->() const { return &s; }
    std::string const& operator*() const { return s; }
    bool operator!() const { return false; }
    bool operator<(my_string const&) const { return false; }
    bool operator==(my_string const& o) const { return this == &o; }
};
//using my_string = std::shared_ptr<const std::string>;
template<typename... T>
my_string make_string( T&&... t ) {
  //  return std::unique_ptr<std::string>( new std::string(std::forward<T>(t)...) );
    return { std::string(std::forward<T>(t)...) };
}

struct order_ptrs_by_value {
  template<class T, class U>
  bool operator()( T&& t, U&& u ) const {
    	if (!t || !u) return t < u;
    return (*t) < (*u);
  }
};
struct equal_ptrs_by_value {
  template<class T, class U>
  bool operator()( T&& t, U&& u ) const {
		if (!t || !u) return t == u;
    return (*t) == (*u);
  }
	
};
struct hash_string {
	template<typename T>
	std::size_t element_hash(T const& t) const { return std::hash<T>{}(t); }
	std::size_t operator()(my_string const& s) const {
		std::size_t seed = 0;
		if (!s) return seed;
		for (auto&& c : *s) {
			seed ^= element_hash(c) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
		}
		return seed;
	}
};

bool compare_strlen (my_string const& lhs, my_string const& rhs) {
	if (!lhs || !rhs) return lhs<rhs;
  return (lhs->length() < rhs->length());
}

int main () {
  std::cin.sync_with_stdio(false);
  auto start = std::chrono::high_resolution_clock::now();
  
  /* Extract unique words and count the number of occurances of each word */
  typedef std::unordered_map<my_string,int, hash_string, equal_ptrs_by_value> my_map;
  //typedef std::map<my_string,int, order_ptrs_by_value> my_map;
  my_map word_count; 

  /* Extract words from the input file, splitting on whitespace */
  {
    std::string str;
    while (std::cin >> str) {
      word_count[make_string(std::move(str))]++;
    }
  }

  std::vector<my_string> words;
  words.reserve(word_count.size());

  for( auto const& wc : word_count ) {
      words.push_back( wc.first );
  }

  // Sort by word length 
  std::sort(words.begin(), words.end(), compare_strlen);

  // Print words with length and number of occurances
  for (auto&& word:words) {
    std::cout << word->length() << " " << word_count[word]  << " " <<
              *word << "\n";
  }
  auto end = std::chrono::high_resolution_clock::now();
  auto delta = end-start;
  std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(delta).count()/1000. << "seconds \n";
  return 0;
}

