Codeforces965E Short Code 【启发式合并】【堆】

题目大意:

  给出总长度不超过1E+5的不重复字符串集,给每个字符串选一个前缀使得可以区分它。

题目分析:

  KAN出的DIV2难度一般不高,想升Ranting的可以试试。

  简单的树上启发式合并,建出Trie树,一开始每个字符串用自己表示,每次向上合并的时候选出堆中最大元素变成当前位置,特判一下有end的地方即可。

  证明也很简单,我们考虑一个根没被选的子树,若我们要使得这个子树的代价最小,那么我们一定要选择一个位置放到根上来,不难发现选择深度最大的点是会最小的。由于树的子结构的关系,这样向上归纳也是正确的。

代码:

  

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int sigma = 26;
 5 
 6 int n,num,len,root;
 7 char str[105000];
 8 struct trie{
 9     int end,sz,nxt[30];
10 }T[105000];
11 
12 int Num(char ch){return ch-'a';}
13 
14 void insert(int now,int pla){
15     if(pla == len) {T[now].sz++;T[now].end=1;return;}
16     int um = Num(str[pla]);
17     if(T[now].nxt[um]){
18     insert(T[now].nxt[um],pla+1);
19     }else{
20     num++; T[now].nxt[um] = num;
21     insert(T[now].nxt[um],pla+1);
22     }
23 }
24 
25 void dfs(int now){
26     for(int i=0;i<sigma;i++)
27     if(T[now].nxt[i]) dfs(T[now].nxt[i]),T[now].sz+=T[T[now].nxt[i]].sz;
28 }
29 
30 void read(){
31     scanf("%d",&n);
32     for(int i=1;i<=n;i++){
33     scanf("%s",str);
34     len = strlen(str);
35     insert(root,0);
36     }
37     dfs(root);
38 }
39 
40 int ans = 0;
41 int bel[102000];
42 priority_queue<int,vector<int>,less<int> > q[102000];
43 
44 int merge(int a,int b){
45     if(q[a].size()<q[b].size()){
46     while(!q[a].empty()){
47         int k = q[a].top();q[a].pop();
48         q[b].push(k);
49     }
50     return b;
51     }else{
52     while(!q[b].empty()){
53         int k = q[b].top();q[b].pop();
54         q[a].push(k);
55     }
56     return a;
57     }
58 }
59 
60 void dfs2(int now,int val){
61     int flag = false;
62     for(int i=0;i<sigma;i++){
63     if(T[now].nxt[i]) flag=true,dfs2(T[now].nxt[i],val+1);
64     }
65     if(!flag){bel[now]=++num;q[num].push(val);return;}
66     for(int i=0;i<sigma;i++){
67     if(T[now].nxt[i]){
68         if(bel[now]){bel[now]=merge(bel[now],bel[T[now].nxt[i]]);}
69         else bel[now] = bel[T[now].nxt[i]];
70     }
71     }
72     if(T[now].end){
73     q[bel[now]].push(val);
74     }else{
75     q[bel[now]].pop();
76     q[bel[now]].push(val);
77     }
78 }
79 
80 void work(){
81     num = 0;
82     for(int i=0;i<sigma;i++){
83     if(!T[root].nxt[i]) continue;
84     dfs2(T[root].nxt[i],1);
85     int hh = bel[T[root].nxt[i]];
86     while(!q[hh].empty()){
87         ans += q[hh].top();q[hh].pop();
88     }
89     }
90     printf("%d",ans);
91 }
92 
93 int main(){
94     read();
95     work();
96     return 0;
97 }

 

posted @ 2018-04-27 13:13  menhera  阅读(746)  评论(3编辑  收藏  举报