#include #include #include #include unsigned int hash(string s) { unsigned int h = 846721; for (int i = 0; i < s.length(); i += 1) h = h * 691 + s[i]; return h; } struct Hashentry { string key; Hashentry * next; Hashentry(string s) { key = s; next = NULL; } }; struct Wordentry: public Hashentry { int count; Wordentry(string s): Hashentry(s) { count = 1; } }; class Hashtable { protected: int size; Hashentry * * table; public: Hashtable(int sz) { size = sz; table = new Hashentry * [size]; for (int i = 0; i < size; i += 1) table[i] = NULL; } void insert(Hashentry * h) { int pos = hash(h->key) % size; h->next = table[pos]; table[pos] = h; } Hashentry * find(string s) { int pos = hash(s) % size; Hashentry * h = table[pos]; while (h != NULL) { if (h->key == s) return h; h = h->next; } return NULL; } ~Hashtable() { for (int p = 0; p < size; p += 1) { Hashentry * h = table[p]; while (h != NULL) { Hashentry * n = h->next; delete h; h = n; } } } void stats() { const int longest = 15; // just a guess int counts[longest+1]; for (int i = 0; i <= longest; i += 1) counts[i] = 0; for (int p = 0; p < size; p += 1) { Hashentry * h = table[p]; int len = 0; while (h != NULL) { len += 1; h = h->next; } if (len > longest) len = longest; counts[len] += 1; } int total = 0; for (int p = 0; p <= longest; p += 1) total += p * counts[p]; double lambda = (double)total/size; double prob = exp(-lambda); for (int p = 0; p <= longest; p += 1) { cout << setw(3) << p << ": got " << setw(9) << counts[p] << setw(9) << (int)(prob * size) << " expected\n"; prob *= lambda / (p+1); } cout << "Total words = " << total << "\n"; } }; int main(int argc, char * argv[]) { int hashsize = atoi(argv[1]); Hashtable ht(hashsize); int words = 0; while (true) { string s; cin >> s; if (cin.fail()) break; Hashentry * h = ht.find(s); if (h == NULL) { Wordentry * w = new Wordentry(s); ht.insert(w); words += 1; } else { Wordentry * w = (Wordentry *) h; w->count += 1; } } ht.stats(); cout << words << " words added\n"; }