uva 11732

字典树;

不过数据量很大;4000*1000;

我用的是传统的方法建树,虽然优化了一下,边插入边统计,不过还是T了;

这是我的代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #define maxn 4000009
 4 using namespace std;
 5 int nonocount;
 6 long long ans;
 7 struct node
 8 {
 9     int num;
10     node *a[62];
11 } no[maxn];
12 
13 node* newnode()
14 {
15     node *p=no+nonocount++;
16     p->num=0;
17     memset(p->a,NULL,sizeof p->a);
18     return p;
19 }
20 
21 void insert(node *root,char *s)
22 {
23     int l=strlen(s);
24     for(int i=0; i<l; i++)
25     {
26         int x;
27         if(s[i]>='0'&&s[i]<='9')x=s[i]-'0';
28         else if(s[i]>='a'&&s[i]<='z')x=s[i]-'a'+10;
29         else if(s[i]>='A'&&s[i]<='Z')x=s[i]-'A'+36;
30         if(root->a[x]==NULL)
31             root->a[x]=newnode();
32         ans+=(root->num)-(root->a[x]->num);
33         root->num++;
34         root=root->a[x];
35     }
36 }
37 char s[1005];
38 int main()
39 {
40     int n,ca=1;
41     while(scanf("%d",&n)&&n)
42     {
43         nonocount=0;
44         node *p=newnode();
45         ans=0;
46         for(int i=0; i<n; i++)
47         {
48             scanf("%s",s);
49             insert(no,s);
50         }
51         printf("Case %d: %lld
",ca++,ans);
52     }
53     return 0;
54 }
View Code

网上的大神的方法是采用左儿子右兄弟的方法建树;

这样节省了很多的时间,受教了!

大神的代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxnode = 4000*1000;
 7 struct trie
 8 {
 9     int left[maxnode]; // 左儿子
10     int right[maxnode]; // 右兄弟
11     int val[maxnode] ; //该节点上有多少串
12     char ch[maxnode]; // 节点表示的字符
13     int cnt ;
14     long long int ans ;
15     void init()
16     {
17         ch[0] = 0, left[0] = right[0] = 0;
18         val[0] = 0;
19         cnt = 1;
20         ans = 0;
21     }
22     void insert(const char *s)
23     {
24         int len = strlen(s) , u = 0,j;
25         for(int i = 0; i <= len ; ++i )
26         {
27             for(j = left[u]; j ; j = right[j])if(ch[j] == s[i]) break; //找到这个节点
28             if(j==0)
29             {
30                 j = cnt++;
31                 ch[j] = s[i];
32                 right[j] = left[u];
33                 left[j] = 0;
34                 left[u] = j;
35                 val[j] = 0;
36             }
37             ans += (val[u] - val[j])*(i << 1|1);
38             if(i == len)
39             {
40                 ans += val[j]*((i+1)<<1);    //特判结尾 Trie中不会进入结尾字符,需特判统计
41                 val[j]++;
42             }
43             val[u]++;
44             u = j;
45         }
46     }
47 } Tri;
48 char tmp[2000];
49 int main()
50 {
51     int n,kase = 1 ;
52     while(scanf("%d",&n)==1 && n)
53     {
54         Tri.init();
55         for(int k=0; k<n; ++k)
56         {
57             scanf("%s",tmp);
58             Tri.insert(tmp);
59         }
60         printf("Case %d: %lld
", kase++, Tri.ans);
61     }
62     return 0;
63 }
View Code
原文地址:https://www.cnblogs.com/yours1103/p/3396635.html