/**
 * c++ 11
 * pour compiler :
 * cc -std=c++11 SWERC_2013_I.cpp -o SWERC_2013_I.out -Wall -Wextra
 *
 * avec cc = g++ ou clang++ selon vos préférences.
 * Je tourne sous archlinux, donc j'ai gcc 4.8, peut-être qu'il vous faudra remplacer
 * -std=c++11 par -std=c++0x
 */

#include <iostream>
#include <map>
#include <list>
#include <string>
#include <algorithm>
#include <vector>

/**
 * Le principe de ce problème est de regarder le nombre d'occurence d'un mot. Il y a deux parties : la lecture et la mise en jour pour tenir compte de la limite des 7 jours.
 *
 * Le principe va être de travailler avec des map et des listes de map pour représenter les 7 jours
 *
 * 
 */

using dico = std::map<std::string,unsigned>;

dico lecture(dico d)
{
    //std::cout<<"lecture";
    std::string s;

    // maintenant qu'on a trouvé le début de la partie à étudié, on regarde tous les mots et on incrémente le dictionnaire
    std::cin>>s;
    while (s != "</text>")
    {
        //std::cout<< s<<"->"<<d[s];
        if(s.size() >= 4)
            ++d[s];
        std::cin>>s;
    }

    return std::move(d);

}




/// affichage de tous les mots
void affiche(const dico &d)
{
    std::for_each(begin(d), end(d), [](const std::pair<std::string,unsigned> &it) 
                  { std::cout<< it.first<<"->"<< it.second << std::endl;});

    /*for(auto it=begin(d); it != end(d); ++it)
      std::cout<< it.first<<"->"<<it.second;*/
}


/// affichage des top n
/// L'idée est de trier la liste et de parcourir en tenant
/// compte des éventuels ex-aequo
void topn(const dico &d, unsigned n)
{
    //std::cout << "affichage de top :: "<< d.size()<<std::endl;
    std::cout << "<top " << n << ">" << std::endl;

    std::vector< std::pair<std::string,unsigned> > dico_trie;
    //dico_trie.resize(d.size());


    // on transfert les éléments du dictionnaire au vecteur d'éléments
    std::for_each(begin(d), end(d), [&dico_trie](std::pair<std::string,unsigned> it) 
                  { dico_trie.push_back(std::move(it));});

    // on trie, d'abord par nombre d'apparition, puis par ordre alphabétique
    std::sort(begin(dico_trie), end(dico_trie), [](const std::pair<std::string,unsigned> &i1, const std::pair<std::string,unsigned> &i2)
              {return i1.second > i2.second 
                      || (i1.second == i2.second && i1.first < i2.first);});

    // on affiche
    // i : indice d'accès au tableau
    // on accède de manière décalée
    unsigned i = 1;
    // k :  numéro (par rapport au nombre que l'on doit afficher)
    unsigned k = 0;
    while (k<n && i <= dico_trie.size())
    {
        // si une entrée vaut 0, on ne l'affiche pas
        if(dico_trie[i-1].second != 0)
            std::cout<< dico_trie[i-1].first<<" "<<  dico_trie[i-1].second <<std::endl;


        //si le numéro change, ça veut dire qu'on passe
        // au numéro suivant
        if(dico_trie[i-1].second != dico_trie[i].second)
            ++k;


        // on incrémente le numéro d'accès au vecteur
        ++i;
    }
    
    std::cout << "</top>"<<std::endl;
}



int main(void)
{

    bool finished =false;
    std::list<dico> l;


    while(!finished)
    {
        std::string s;
        //std::cout<<"début lecture";
        // on commence par chercher le début du texte :  on cherche le <text> correspondant
        // si on rencontre un <top, alors on affiche le nombre de résultat
        std::cin >> s;
        // std::cout<<s;
        while (s != "<text>")
        {
            if(s == "<top")
            {
                unsigned n;
                std::cin >> n;
                topn(l.back(),n);
            }
            // std::cout<<s;
            std::cin >> s;
        }
        

        /// une fois qu'on a recontré le début, il faut insérer les mots
        // on commence par récupérer l'ancien dictionnaire
        dico d;
        if(l.size() != 0)
            d =l.back();

        // on le remplit
        d = lecture(d);
        //affiche(d);
        //std::cout << "mise à jour";
        // on le met à jour si plus de 7 jours ont passé.
        if(l.size() >= 7)
        {
            std::for_each(l.front().begin(), l.front().end(),
                          [&d](const std::pair<std::string,unsigned> mot)
                          {d[mot.first] -= mot.second;});
            l.pop_front();
        }

        // on ajoute le dictionnaire à notre liste de dictionnaires
        l.push_back(d);
    }


    return 0;



}

/*
<text>
imagine you are in the hiring process of a company whose
main business is analyzing the information that appears
in the web
</text>
<text>
a simple test consists in writing a program for
maintaining up to date a set of trending topics
</text>
<text>
you will be hired depending on the efficiency of your solution
</text>
<top 5 />
<text>
they provide you with a file containing the text
corresponding to a highly active blog
</text>
<text>
the text is organized daily and you have to provide the
sorted list of the n most frequent words during last week
when asked
</text>
<text>
each input file contains one test case the text corresponding
to a day is delimited by tag text
</text>
<text>
the query of top n words can appear between texts corresponding
to two different days
</text>
<top 3 />
<text>
blah blah blah blah blah blah blah blah blah
please please please
</text>
<top 3 />


*/
