Wczytywanie do vector<pair> - zliczanie wystąpień stringa w vector oraz sortowanie

0

Witam, mam pewien mały problem z zadaniem http://pl.spoj.com/problems/NAMES/ Wczytuje ciag, wrzucam imie do vector<pair> pozniej sortuje imiona i wypisuje wyniki. Dla testowych danych program działa poprawnie, z innymi co wpisywałem również. Tylko już w spoj zadanie nie przechodzi, bo albo wyrzuci 'przekroczono czas' lub 'błędne wyniki' próbowałem również, wczytywać dane przy pomocy while(getline(cin, ciag)) , a pozniej tego stringa ciąłem, aby wyciągnąć z niego imie, tak jak to jest pokazane poniżej w listingu programu. Dla przykładu podaje linka do ideone z przykładem ze spoj: http://ideone.com/YJQOsB tylko tutaj mam warunek ustawiony na 7 aby nie wczytywać więcej linii. W programie poniżej mam ustawione na 100000. Moje pytanie brzmi, co może być z tym programem nie tak, że nie przechodzi, mimo dobrych wyników? Byłbym wdzięczny za jakieś wskazówki, bo ja już nie mam żadnego pomysłu :)
Proszę o wyrozumiałość dla początkującego, jeśli ten kod nie jest idealny, dopiero się uczę :)

 
#include <iostream>
#include <string>
#include <algorithm>
#include <utility>
#include <vector>

using namespace std;

struct sort_names {
    bool operator()(const std::pair<string, int> &left, const std::pair<string, int> &right) {
        return left.first < right.first;
    }
};

struct sort_values {
    bool operator()(const std::pair<string, int> &left, const std::pair<string, int> &right) {
        return left.second > right.second;    
    }    
};

void show(const vector< pair<string, int> > names) {
    for(int i = 0; i < names.size(); ++i)
        cout << names[i].first << " " << names[i].second << endl;    
}

int main() {
//  string ciag, imie;
    string ciag, a, b, imie;
    bool flag = true;
    int end = 0;
    vector< pair<string, int> > names; // vector na ktorym operaujemy

//  while(getline(cin, ciag)) {  
    while(cin >> a >> b >> imie) {
//      transform(ciag.begin(), ciag.end(), ciag.begin(), ::toupper); // wszystko do duzych liter
        transform(imie.begin(), imie.end(), imie.begin(), ::toupper); // imie do duzej litery
//      imie =  ciag.substr(ciag.find_last_of(" ") + 1, ciag.length()); // wyciagniecie podciagu (imienia)
        
        for(int i = 0; i < names.size(); ++i) { // przeszukaj caly vector w poszukiwaniu podobnego imienia
            if(names[i].first == imie) {
                names[i].second++;
                flag = false; // jesli znaleziono to zwieksz jego ilosc
            }
        }
        
        if(flag) { // jesli nie znaleziono tych samych imion to dodajemy nowe imie
            names.push_back(std::make_pair(imie, 1));
            flag = true;
        
        }

        // czy to trzeba rozdzielic na dwa sortowania ?
        sort(names.begin(), names.end(), sort_names()); // sortowanie vectora po imionach
        sort(names.begin(), names.end(), sort_values()); // sortowanie vectora po values
    //    show(names); // pokazuje vector  / czy musi byc w tej petli czy poza petla ?

        flag = true; // reset flagi

        ++end;
        if(end >= 100000) break;
    }
    show(names);

    return 0;    
}
1
void show(const vector< pair<string, int> > names) {
    for(int i = 0; i < names.size(); ++i)
        cout << names[i].first << " " << names[i].second << endl;    
}

Kopiujesz cały wektor.

sort(names.begin(), names.end(), sort_names()); // sortowanie vectora po imionach
sort(names.begin(), names.end(), sort_values()); // sortowanie vectora po values

wtf? To nie jest stable sort, wynik pierwszego sortowania jest kompletnie nadpisywany przez wynik drugiego.
Dlaczego robisz to w każdej iteracji pętli?

        for(int i = 0; i < names.size(); ++i) { // przeszukaj caly vector w poszukiwaniu podobnego imienia
            if(names[i].first == imie) {
                names[i].second++;
                flag = false; // jesli znaleziono to zwieksz jego ilosc
            }
        }

Skoro już masz posortowany wektor, to może binary search?

Ogółem, kłania się nieznajomość biblioteki standardowej. Zamiast prawie całości pętli byś mógł napisać

m[imie]++;

gdybyś zdefiniował m jako map<string,int>.

2
#include <map>
#include <vector>
#include <string>
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;

typedef pair<string,unsigned> order;
bool cmp(const order &A,const order &B) { return (A.second!=B.second)?(A.second>B.second):(A.first<B.first); }
string strupr(const char *str) { string s(str); transform(s.begin(),s.end(),s.begin(),::toupper); return s; }

int main()
  {
   char buff[21];
   map<string,unsigned> Map;
   while(scanf(" %*d%*c%*c%*s%*c%s",buff)==1) ++Map[strupr(buff)];
   vector<order> Tb(Map.size());
   copy(Map.begin(),Map.end(),Tb.begin());
   sort(Tb.begin(),Tb.end(),&cmp);
   for(vector<order>::iterator i=Tb.begin();i!=Tb.end();++i) printf("%s %d\n",i->first.c_str(),i->second);
   return 0;
  }

1 użytkowników online, w tym zalogowanych: 0, gości: 1