UVA 11732——Trie

解题思路:

  首先我们可以发现:

    1.若两个字符串A、B不相等,且它们的公共前缀为S,则它们的比较次数为:2 * len(S) + 1;

    2.若两个字符串相等,设为A,则它们的比较次数为 2 * ( len(A) + 1 )    //注意考虑结束符'\0'

  那么我们可以建立前缀树,在向前缀树中插入字符串的过程中,如果遇到分叉结点则需要进行比较。

  特别注意:"aaaa","aa"以及"aaaa","aaaa"的情况

  具体做法:

    Trie维护每个结点的val和flag,其中val表示经过每个结点的字符串个数,flag表示是否是分叉结点。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cctype>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int maxnode = 4000*1000 + 10;
 9 const int _size = 63;
10 long long ans;
11 
12 struct Trie {
13     int ch[maxnode][_size];
14     int val[maxnode];
15     int flag[maxnode];
16     int sz;
17     Trie() {
18         sz = 1;
19         memset(ch[0], 0, sizeof (ch[0]));
20     }
21     int idx(int c) {
22         if(c == '\0') return 62;
23         else if(isdigit(c)) return c - '0';
24         else if(c >= 'A' && c <= 'Z') return c - 'A' + 10;
25         else return c - 'a' + 36;
26     }
27     
28     void insert(char *s) {
29         int u = 0, n = strlen(s);
30         val[u]++;
31         int i;
32         for(i = 0; i <= n; i++) {
33             int c = idx(s[i]);
34             if(!ch[u][c]) {
35                 memset(ch[sz], 0, sizeof (ch[sz]));
36                 ch[u][c] = sz++;
37                 val[ch[u][c]] = 1;
38                 if(val[u] > 1){
39                     flag[u] = 1;
40                     ans += (2*i+1) * (val[u]-val[ch[u][c]]);
41                 }
42             }
43             else {
44                 val[ch[u][c]]++;
45                 if(flag[u]) ans += (2*i+1) * (val[u]-val[ch[u][c]]);
46             }
47             u = ch[u][c];
48             
49         }
50         if(val[u] > 1) {
51             flag[u] = 1;
52             ans += (2*i) * (val[u]-1);
53         }
54     }
55     
56     void clear() {
57         sz = 1;
58         memset(val, 0 , sizeof val);
59         memset(ch[0], 0, sizeof (ch[0]));
60         memset(flag, 0, sizeof flag);
61     }
62 };
63 
64 char s[1010];
65 Trie T;
66 
67 int main(int argc, const char * argv[]) {
68    
69     int n;
70     int kase = 1;
71     while(scanf("%d", &n) == 1 && n) {
72         T.clear();
73         ans = 0;
74         for(int i = 0; i < n; i++) {
75             scanf("%s", s);
76             T.insert(s);
77         }
78         
79         printf("Case %d: %lld\n", kase++, ans);
80     }
81     return 0;
82 }

 

posted @ 2016-11-09 11:52  kiraa  阅读(255)  评论(0编辑  收藏  举报