最短的名字 字典树

来源:互联网 发布:淘宝中国质造加入条件 编辑:程序博客网 时间:2024/06/06 03:52

在一个奇怪的村子中,很多人的名字都很长,比如aaaaa, bbb and abababab。
名字这么长,叫全名显然起来很不方便。所以村民之间一般只叫名字的前缀。比如叫’aaaaa’的时候可以只叫’aaa’,因为没有第二个人名字的前三个字母是’aaa’。不过你不能叫’a’,因为有两个人的名字都以’a’开头。村里的人都很聪明,他们总是用最短的称呼叫人。输入保证村里不会有一个人的名字是另外一个人名字的前缀(作为推论,任意两个人的名字都不会相同)。
如果村里的某个人要叫所有人的名字(包括他自己),他一共会说多少个字母?
Input
输入第一行为数据组数T (T<=10)。每组数据第一行为一个整数n(1<=n<=1000),即村里的人数。以下n行每行为一个人的名字(仅有小写字母组成)。输入保证一个村里所有人名字的长度之和不超过1,000,000。
Output
对于每组数据,输出所有人名字的字母总数。

Sample Input
1
3
aaaaa
bbb
abababab
Sample Output
5

代码:

#include <iostream>#include <string>#include <cstring>#include <cstdio>#include <cmath>#include <cstdlib>#include <algorithm>#include <queue>#include <map>#include <vector>#define MM(s,q) memset(s,q,sizeof(s))#define INF 0x3f3f3f3f#define MAXN 200005#define Lchild id<<1#define Rchild (id<<1)+1using namespace std;typedef struct Tree {    struct Tree *next[26];    int time;};Tree *root;int ans;void clears(Tree *p) {    for (int i = 0; i < 26; i++)        if (p->next[i] != NULL)            clears(p->next[i]);    free(p);}void Insert(char *s) {    Tree *q = root, *tmp;    for (int i = 0; i < strlen(s); i++) {        int k = s[i] - 'a';        if (q->next[k] == NULL) {            tmp = new Tree;            for (int i = 0; i < 26; i++) tmp->next[i] = NULL;            tmp->time = 0;            q->next[k] = tmp;        }        q->time++;        q = q->next[k];    }    q->time++;}void Find(Tree *p, int num) {    if (p->time == 1) {        ans += num;        return;    }    for (int i = 0; i < 26; i++)        if (p->next[i] != NULL)            Find(p->next[i], num + 1);}int main() {    int T, n;    char s[1000000];    cin >> T;    while (T--) {        cin >> n;        root = new Tree;        for (int i = 0; i < 26; i++) root->next[i] = NULL;        root->time = 0;        for (int i = 1; i <= n; i++) {            scanf("%s", s);            Insert(s);        }        ans = 0;        Find(root, 0);        printf("%d\n", ans);        clears(root);    }}
0 0
原创粉丝点击