/* Copyright (C) 2014 by Alexandru Cojocaru */ /* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #define _GNU_SOURCE #include #include #include static int totana; /* insert sort */ static void inssort (char *a, int len) { for (int i = 1; i < len; ++i) { for (int j = i; j > 0; --j) { if (a[j-1] <= a[j]) break; char t = a[j-1]; a[j-1] = a[j]; a[j] = t; } } } /* ternary search tree (tst) */ typedef struct tst tst; struct tst { tst *l, *r, *d; int c; }; static tst * tstnewnode (int c) { tst *r = calloc (1, sizeof (*r)); if (r == NULL) assert (! "out of memory!!"); r->c = c; return r; } static tst * tstinsr (tst *r, char *s, int *new) { if (! r) { r = tstnewnode (*s); if (*s == '\0') *new = 1; } if (*s < r->c) r->l = tstinsr (r->l, s, new); else if (*s > r->c) r->r = tstinsr (r->r, s, new); else { if (*s != '\0') r->d = tstinsr (r->d, ++s, new); } return r; } /* return: 0 if new entry, 1 if already inserted */ static int tstins (tst **r, char *s) { int new = 0; *r = tstinsr (*r, s, &new); return (! new); } static char *line; static size_t linesz; static void readwords (FILE *s) { tst *r = NULL; int n; while ((n = getline (&line, &linesz, s)) > 0) { if (line[n-1] == '\n') { line[n-1] = '\0'; --n; } inssort (line, n); totana += tstins (&r, line); } } int main (int argc, char *argv[]) { readwords (stdin); printf ("%d\n", totana); }