// written in ed because cellphone keyboards suck at vi #include #include #include void *xmalloc(size_t n) { void *p = malloc(n); if (!p) abort(); return p; } char *xstrdup(char *s) { char *p = strdup(s); if (!p) abort(); return p; } typedef struct node { char *s; int count; struct node *next; } node; enum { hash_size = 32768 }; typedef struct table { node *a[hash_size]; } table; table words; uint32_t hash(char *s) { uint32_t h = 0; while (*s) { h *= 17903; h += *s++; } return h; } node *upsert(table *h, char *s) { node **n = &h->a[hash(s) & (hash_size - 1)]; for (; *n; n = &(*n)->next) { if (0 == strcmp(s, (*n)->s)) return *n; } node *m = xmalloc(sizeof(*m)); *m = (node) { xstrdup(s) }; *n = m; return m; } void print_words(table *t) { for (size_t i = 0; i != hash_size; i++) { for (node *n = t->a[i]; n; n = n->next) { printf("%8d %s\n", n->count, n->s); } } } int max_chain(table *t) { int max = 0; for (size_t i = 0; i != hash_size; i++) { int len = 0; for (node *n = t->a[i]; n; n = n->next) { len++; } if (len > max) max = len; } return max; } #ifdef NO_HASHING #define upsert(...) (&dummy) #endif node dummy; int main(int argc, char **argv) { char buf[128]; for (;;) { if (!fgets(buf, sizeof buf, stdin)) break; char *p = buf; for (char *q = buf; *q; q++) { char c = *q; if ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') { if (!*p) p = q; continue; } *q = 0; if (strlen(p)) upsert(&words, p)->count++; p = q; } if (strlen(p)) upsert(&words, p)->count++; } print_words(&words); printf("dummy count %d", dummy.count); fprintf(stderr, "max chain %d\n", max_chain(&words)); return 0; }