Uva 11732 strcmp()函数

题目链接:https://vjudge.net/contest/158125#problem/A

题意:

系统中,strcmp函数是这样执行的,给定 n 个字符串,求两两比较时,strcmp函数要比较多少次?

如:

t  h  a  n         t  h  e  r  e  

t  h  a  t          t  h  e  

2  2  2  1            2  2  2  1

直接两两比较是超时的。

可以这样建立一个字典树:

可以发现一直要比较到交叉处,和这个交叉点的深度有关(2*depth+1)。

1、这个字典序每一个交叉点都是要计算的,所以采用邻接表的形式存图;

2、每个结点都要计算他的叶子结点的个数,当分叉的时候,那么说明这里有两个(多个)不同的单词,从中要选择两个单词,计算有多少种搭配,比较次数就是这些搭配*(2*depth+1);

3、递归找下一个结点。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxnode = 4000 * 1000 + 10;
 6 const int sigma_size = 26;
 7 
 8 struct Trie
 9 {
10     int head[maxnode];
11     int next[maxnode];
12     char ch[maxnode];
13     int tot[maxnode];
14     int sz;
15     long long ans;
16     void clear()
17     {
18         sz = 1;
19         tot[0] = head[0] = next[0] = 0;
20     }
21 
22     void insert(const char *s)
23     {
24         int u = 0, v, n = strlen(s);
25         tot[0]++;
26         for(int i = 0; i <= n; i++)
27         {
28             // 找字符a[i]
29             bool found = false;
30             for(v = head[u]; v != 0; v = next[v])
31                 if(ch[v] == s[i])   // 找到了
32                 {
33                     found = true;
34                     break;
35                 }
36             if(!found)
37             {
38                 v = sz++; // 新建结点
39                 tot[v] = 0;
40                 ch[v] = s[i];
41                 next[v] = head[u];
42                 head[u] = v; // 插入到链表的首部
43                 head[v] = 0;
44             }
45             u = v;
46             tot[u]++;
47         }
48     }
49 
50 
51     void dfs(int depth,int u)
52     {
53         if(head[u]==0) //叶子节点
54             ans+=tot[u]*(tot[u]-1)*depth;
55         else
56         {
57             int sum =0;
58             for(int v=head[u]; v!=0; v=next[v])
59             {
60                 sum+=tot[v]*(tot[u]-tot[v]);
61             }
62             ans+=sum/2*(2*depth+1);
63             for(int v=head[u]; v!=0; v=next[v])
64                 dfs(depth+1,v);
65         }
66     }
67 
68     long long count()
69     {
70         ans = 0;
71         dfs(0,0);
72         return ans;
73     }
74 
75 } trie;
76 
77 char word[1010];
78 
79 int main()
80 {
81     int n;
82     int kase = 1;
83     while(scanf("%d",&n),n)
84     {
85         trie.clear();
86         for(int i=0; i<n; i++)
87         {
88             scanf("%s",word);
89             trie.insert(word);
90         }
91         printf("Case %d: %lld
",kase++,trie.count());
92     }
93 
94     return 0;
95 }
View Code
原文地址:https://www.cnblogs.com/TreeDream/p/6691301.html