Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Sortowanie mapy

Ostatnio zmodyfikowano 2015-10-09 13:46
Autor Wiadomość
Asahel
Temat założony przez niniejszego użytkownika
Sortowanie mapy
» 2015-10-04 15:29:17
Witam, rozwiązuję zadanie: http://pl.spoj.com/problems​/NAMES/. Zastanawiam się jak posortować mapę względem drugiej współrzędnej tj. liczba wystąpień imienia w wprowadzanych stringu.

C/C++
#include <iostream>
#include<string>
#include<map>

using namespace std;


int main()
{
   
   
    string nr, nazwisko, imie;
    map < string, int > osoba;
    //wsadzamy imię do mapy, jak się powtorzy to zwiekszamy drugi parametr o 1
    while( cin >> nr >> nazwisko >> imie )
    {
        //petla zamieniajaca duze litery na male - tego wymaga polecenie
        for( int i = 0; i < imie.length(); i++ )
        {
            if( imie[ i ] >= 97 && imie[ i ] <= 122 )
            {
                imie[ i ] = imie[ i ] - 32;
            }
        }
        ++osoba[ imie ];
    }
   
   
    //wypisujemy pare imie i liczba wystapien wedlug porzadku alfabetycznego
    for( map < string, int >::const_iterator it = osoba.begin();
   
    it != osoba.end(); ++it )
   
    {
       
        cout << it->first << "\t" << it->second << endl;
       
    }
   
   
   
}
P-138153
pekfos
» 2015-10-04 18:05:26
Skopiuj dane do innej struktury danych, np wektora par.
P-138157
Asahel
Temat założony przez niniejszego użytkownika
» 2015-10-04 21:54:38
Tak zrobiłem. Program wygląda jak niżej. Niestety spoj nie akaceptuje tego rozwiązania! Pomimo, że przykładowy inpout z treści zadania daje identyczny output jak w treści :( No i czas wykonania też jest przerażający :(

C/C++
#include <iostream>
#include<string>
#include<map>
#include<vector>
#include <algorithm>

using namespace std;

typedef std::pair < string, int > my_pair;

bool sort_pred( const my_pair & left, const my_pair & right )
{
    return left.second > right.second;
}


int main()
{
   
   
    string nr, nazwisko, imie;
    map < string, int > osoba;
    vector < my_pair > data;
    //wsadzamy imię do mapy, jak się powtorzy to zwiekszamy drugi parametr o 1
    while( cin >> nr >> nazwisko >> imie )
    {
        for( int i = 0; i < imie.length(); i++ )
        {
            if( imie[ i ] > 90 )
            {
                imie[ i ] = imie[ i ] - 32;
            }
        }
        ++osoba[ imie ];
    }
   
    for( map < string, int >::const_iterator it = osoba.begin(); it != osoba.end(); ++it )
    {
        data.push_back( make_pair( it->first, it->second ) );
    }
   
    sort( data.begin(), data.end(), sort_pred );
   
    for( int i = 0; i < data.size(); i++ )
    {
        cout << data[ i ].first << " " << data[ i ].second << endl;
    }
   
   
   
   
   
   
}
P-138164
michal11
» 2015-10-04 23:02:28
Zadeklaruj rozmiar vectora na 100 000.
Użyj toupper() zamiast ifa i odejmowania jakichś wartości.

Jeżeli to nie zadziała ( a zapewne nie zadziała) to znalazłem jeszcze coś takiego http://stackoverflow.com​/questions/5056645​/sorting-stdmap-using-value.
P-138165
Monika90
» 2015-10-04 23:55:19
sortowanie jest niestabilne, zamień sort na stable_sort i zobacz czy przejdzie.

Albo zostaw sort, ale zmień predykat na
C/C++
bool sort_pred( const my_pair & left, const my_pair & right )
{
    return left.second > right.second || left.second == right.second && left.first < right.first;
}
i powiedz nam która wersja działa szybciej.
P-138166
carlosmay
» 2015-10-05 05:23:24
C/C++
map < string, int >::const_iterator itr_end = osoba.end();
for( map < string, int >::const_iterator it = osoba.begin(); it != itr_end; ++it )

Może to coś przyspieszy.
P-138167
Asahel
Temat założony przez niniejszego użytkownika
» 2015-10-05 22:43:48
Dziękuję za odpowiedzi. Zamieniłem sort na stable_sort i program został zaakceptowany przez spoja. Jedynym problem pozostaje wydajność, którą należy dopracować. Jestem bardzo ciekawy z czego korzystały osoby, które osiągnęły czasy bliskie 0.00. Jakieś pomysły?
P-138192
withelm
» 2015-10-09 13:46:30
Jednym z szybszych rozwiązań jest np to:
1. Tworzysz sobie puste drzewo TRIE(https://pl.wikipedia.org/wiki/Drzewo_trie).
2. Dodajesz każde imię(małe znaki zamieniasz na wielki) w tym drzewie i w przypadku gdy kończy się dane imię to:
a) ustawiasz flagę, że to koniec imienia
b) dodajesz +1 do licznika wystąpień tego konkretnego imienia
3. Odczytujesz wynik DFS i w przypadku gdy widzisz zaznaczoną flagę wypisujesz imie + licznik wystąpień.

gdzie n to suma znaków imion
Całkowita złożoność tego rozwiązania to O(n)

Twoje jest wolne ponieważ ma O(n log(n)). Dodatkowo korzystasz z mapy która jest wolna do tego typu zadań.

Plus na spoju stosuje się sztuczki, z szybkim wczytywaniem (http://ftp.tuwien.ac.at/languages/c/programming-bbrown/c_075.htm)
P-138315
« 1 »
  Strona 1 z 1