Stavo cercando di risolvere this problem from acm.timus.ru che fondamentalmente vuole che io produca il numero di sottostringhe diverse di una determinata stringa (lunghezza massima 5000).In che modo std :: set è più lento di std :: map?
Le soluzioni che sto per presentare sono disperatamente inefficienti e condannate per il tempo limite superato il verdetto dati i vincoli. Tuttavia, l'unico modo in cui queste due soluzioni differiscono (almeno per quanto posso vedere/comprendere) è che si utilizza std::map<long long, bool>
, mentre l'altro utilizza std::set <long long>
(vedere l'inizio dell'ultimo ciclo per. può controllare con qualsiasi strumento diff). La soluzione della mappa risulta in "Limite temporale superato nel test 3", mentre la soluzione impostata risulta in "Limite temporale superato nel test 2", il che significa che il test 2 è tale che la soluzione mappa funziona più rapidamente rispetto alla soluzione impostata. Questo è il caso se scelgo il compilatore Microsoft Visual Studio 2010. Se scelgo GCC, entrambe le soluzioni risultano in TLE nel test 3.
Non sto chiedendo come risolvere il problema in modo efficiente. Quello che sto chiedendo è come si può spiegare che l'utilizzo di std::map
può apparentemente essere più efficiente rispetto all'utilizzo di std::set
. Non riesco a vedere i meccanismi di questo fenomeno e spero che qualcuno possa avere qualche intuizione.
Code1 (usa carta, TLE 3):
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;
int main()
{
string s;
cin >> s;
vector <long long> p;
p.push_back(1);
for (int i = 1; i < s.size(); i++)
p.push_back(31 * p[i - 1]);
vector <long long> hash_temp;
hash_temp.push_back((s[0] - 'a' + 1) * p[0]);
for (int i = 1; i < s.size(); i++)
hash_temp.push_back((s[i] - 'a' + 1) * p[i] + hash_temp[i - 1]);
int n = s.size();
int answer = 0;
for (int i = 1; i <= n; i++)
{
map <long long, bool> hash_ans;
for (int j = 0; j < n - i + 1; j++)
{
if (j == 0)
hash_ans[hash_temp[j + i - 1] * p[n - j - 1]] = true;
else
hash_ans[(hash_temp[j + i - 1] - hash_temp[j - 1]) * p[n - j - 1]] = true;
}
answer += hash_ans.size();
}
cout << answer;
}
Code2 (usa insieme, TLE 2):
#include <iostream>
#include <string>
#include <vector>
#include <set>
using namespace std;
int main()
{
string s;
cin >> s;
vector <long long> p;
p.push_back(1);
for (int i = 1; i < s.size(); i++)
p.push_back(31 * p[i - 1]);
vector <long long> hash_temp;
hash_temp.push_back((s[0] - 'a' + 1) * p[0]);
for (int i = 1; i < s.size(); i++)
hash_temp.push_back((s[i] - 'a' + 1) * p[i] + hash_temp[i - 1]);
int n = s.size();
int answer = 0;
for (int i = 1; i <= n; i++)
{
set <long long> hash_ans;
for (int j = 0; j < n - i + 1; j++)
{
if (j == 0)
hash_ans.insert(hash_temp[j + i - 1] * p[n - j - 1]);
else
hash_ans.insert((hash_temp[j + i - 1] - hash_temp[j - 1]) * p[n - j - 1]);
}
answer += hash_ans.size();
}
cout << answer;
}
Hai provato qualcosa da solo, come misurare da solo il tempo? o addirittura profilazione? – PlasmaHH
@PlasmaHH: Credo di aver dato prove sufficienti del fatto che uno è più lento dell'altro. Sono interessato a come sia possibile –
@PlasmaHH: credo che questa sia una domanda perfettamente adeguata. –