大意:告诉你一些字符串 让你组成字典树,

然后定义每个节点到所有叶子节点的距离的和等于改点的value

当根节点只有一个孩子,该根节点也算一个叶子节点

问所有节点的value的最小值

分析:

开始做的时候  就想的是   枚举每个点  然后求它到所有叶子节点的和  求任意两点的最近距离  用公共祖先来求

于是就有了这个算法

需要预处理出来所有的叶子节点

不能单纯的用字典树的flag来记录  例如插入aaa aa a  那么 a  aa aaa 都会被当成叶子节点

对于这里的处理 我是排了一次序  把节点的最后值用flag标记

然后就是判断根节点是否只有一个孩子

如果只有孩子  那么就加入孩子节点的数组

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<queue>
  6 #include<vector>
  7 #include <set>
  8 using namespace std;
  9
 10 const int MAXN = 100010;
 11 const int PP = 30;
 12 const int maxn = MAXN;
 13
 14
 15 int tire[maxn][30];
 16 int flag[maxn];
 17 int ceng[maxn];
 18
 19 class LCA_RMQ
 20 {
 21 public:
 22     int n;
 23     int pow2[PP];
 24     int tim;
 25     int first[MAXN];
 26     int nodeId[MAXN*2];
 27     int dep[MAXN*2];
 28     int dp[MAXN*2][PP];
 29     bool vis[MAXN];
 30     vector<int> edge[MAXN];
 31
 32     void init(int n)
 33     {
 34         for(int i = 0; i < PP; i++)
 35             pow2[i] = (1<<i);
 36
 37         for(int i = 0; i <= n; i++)
 38         {
 39             edge[i].clear();
 40             vis[i] = false;
 41         }
 42
 43     }
 44
 45     void addedge(int u ,int v)
 46     {
 47         edge[u].push_back(v);
 48     }
 49
 50     void dfs(int u ,int d)
 51     {
 52         tim++;
 53         vis[u] = true;
 54         nodeId[tim] = u;
 55         first[u] = tim;
 56         dep[tim] = d;
 57         int sz = edge[u].size();
 58         for(int i = 0; i < sz; i++)
 59         {
 60             int v = edge[u][i];
 61             if(vis[v] == false)
 62             {
 63                 dfs(v, d + 1);
 64                 tim++;
 65                 nodeId[tim] = u;
 66                 dep[tim] = d;
 67             }
 68         }
 69     }
 70
 71     void ST(int len)
 72     {
 73         int k = (int)(log(len+1.0) / log(2.0));
 74
 75         for(int i = 1; i <= len; i++)
 76             dp[i][0] = i;
 77
 78         for(int j = 1; j <= k; j++)
 79             for(int i = 1; i + pow2[j] - 1 <= len; i++)
 80             {
 81                 int a = dp[i][j-1];
 82                 int b = dp[i+pow2[j-1]][j-1];
 83                 if(dep[a] < dep[b]) dp[i][j] = a;
 84                 else dp[i][j] = b;
 85             }
 86     }
 87
 88     int RMQ(int x ,int y)
 89     {
 90         int k = (int)(log(y-x+1.0) / log(2.0));
 91         int a = dp[x][k];
 92         int b = dp[y-pow2[k]+1][k];
 93         if(dep[a] < dep[b]) return a;
 94         else return b;
 95     }
 96
 97     int LCA(int u ,int v)
 98     {
 99         if(u > v) swap(u, v);
100         int x = first[u];
101         int y = first[v];
102         if(x > y) swap(x,y);
103         int index = RMQ(x,y);
104         return nodeId[index];
105     }
106 };
107 LCA_RMQ t;
108
109 int tot;
110 void Insert(string s,int rt)
111 {
112     ceng[rt] = 0;
113     int len=s.length();
114     for(int i=0;i<len;i++)
115     {
116         int x=s[i]-'a';
117         if(tire[rt][x]==0) {
118             tire[rt][x]=tot++;
119             ceng[tire[rt][x]] = i + 1;
120             t.addedge(rt, tire[rt][x]);
121         }
122 //rt        printf("%c %d  %d\n", x + 'a', tire[rt][x], ceng[tire[rt][x]]);
123         rt=tire[rt][x];
124         flag[rt] = 0;
125     }
126     flag[rt]=1;
127 }
128
129 char str[55][15];
130 set<string> ss;
131 int ye[maxn];
132 int main()
133 {
134     int tt;
135     scanf("%d",&tt);
136     for(int kase = 1; kase <= tt; kase++) {
137         int n;
138         scanf("%d",&n);
139         tot = 1;
140         memset(tire, 0, sizeof(tire));
141         memset(flag, 0, sizeof(flag));
142         memset(ceng, 0, sizeof(ceng));
143         tot = 2;
144         t.init(100000);
145         ss.clear();
146         string s1;
147         for(int i = 0; i < n; i++) {
148             getchar();
149             cin >> s1;
150             ss.insert(s1);
151         }
152
153     set<string>::iterator it;
154 for(it = ss.begin(); it != ss.end(); it++) {
155     s1 = *it;
156     Insert(s1, 1);
157 }
158         t.n = tot;
159         t.tim = 0;
160         t.dfs(1, 1);
161         t.ST(2 * t.n - 1);
162         int ye_tot = 0;
163         for(int i = 1; i < tot; i++) {
164             if(flag[i] == true) {
165                 ye[ye_tot++] = i;
166             }
167         }
168         int hh = 0;
169         for(int i = 0; i < 26; i++) {
170             if(tire[1][i] != 0) {
171                 hh++;
172             }
173         }
174         if(hh == 1) {
175             ye[ye_tot++] = 1;
176         }
177 //        for(int i = 0; i< ye_tot; i++) {
178 //            printf("%d ", ye[i]);
179 //        }puts("");
180         int ans = 1000000000;
181         for(int i = 1; i < tot; i++) {
182             int sum = 0;
183             for(int j = 0; j < ye_tot; j++) {
184                 int rt = t.LCA(i, ye[j]);
185                 sum += fabs(ceng[i] - ceng[rt]) + fabs(ceng[ye[j]] - ceng[rt]);
186             }
187
188             ans = min(ans, sum);
189         }
190         printf("Case #%d: %d\n",kase, ans);
191     }
192     return 0;
193 }

View Code

第二种方法  直接对每个点dfs  由于总共的点数为500个  所用时间复杂度用500*500

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5
 6 const int maxn = 505;
 7
 8
 9 struct Edge {
10     int to, next;
11 }e[maxn];
12 int sum;
13 int head[maxn];
14
15 void add(int u, int v) {
16     e[sum].to = v;
17     e[sum].next = head[u];
18     head[u] = sum++;
19 }
20
21
22 int tire[maxn][30];
23 int tot;
24
25
26 void init() {
27     memset(tire, 0, sizeof(tire));
28     memset(head, 0, sizeof(head));
29     sum = 1;
30     tot = 1;
31 }
32
33 void Insert(char *s, int rt) {
34     for(int i = 0; s[i]; i++) {
35         int x = s[i] - 'a';
36         if(tire[rt][x] == 0) {
37             tire[rt][x] = tot++;
38             add(rt, tire[rt][x]);
39             add(tire[rt][x], rt);
40         }
41 //        printf("%c   %d\n", s[i], tire[rt][x]);
42         rt = tire[rt][x];
43     }
44 }
45
46 int ans;
47
48 int vis[maxn];
49 void dfs(int u, int de) {
50     vis[u] = 1;
51     bool flag = false;
52     for(int i = head[u]; i; i = e[i].next) {
53         int v = e[i].to;
54         if(!vis[v]) {
55             vis[v] = 1;
56             flag = true;
57             dfs(v, de + 1);
58         }
59     }
60     if(flag == false) {
61         ans += de;
62     }
63 }
64
65 int main() {
66     int t, n;
67     char str[15];
68     scanf("%d",&t);
69     int ka = 1;
70     while(t--) {
71         scanf("%d",&n);
72         init();
73         while(n--) {
74             scanf("\n%s",str);
75 //            printf("%s\n",str);
76             Insert(str, 0);
77         }
78         int _ans = 1000000000;
79         for(int i = 0; i < tot; i++) {
80             ans = 0;
81             memset(vis, 0, sizeof(vis));
82             dfs(i, 0);
83             _ans = min(_ans, ans);
84         }
85         printf("Case #%d: %d\n",ka++,_ans);
86     }
87 }

View Code

转载于:https://www.cnblogs.com/zhanzhao/p/4773996.html

hust1350Trie【字典树+dfs || 字典树 + LCA】相关推荐

  1. HDU - 5788 Level Up(主席树+dfs序+树状数组)

    题目链接:点击查看 题目大意:给出一棵有向树,每个节点都有一个初始的权值 a[ i ] ,和一个通过计算得到的权值 mid[ i ] ,mid 数组的计算方法如下:mid[ u ] 为结点 u 及其子 ...

  2. bzoj 2434 [Noi2011]阿狸的打字机(AC自动机+fail树+dfs序+树状数组)

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 3521  Solved: 1913 [Submit][S ...

  3. POJ 3764 Language: The xor-longest Path (01字典树+DFS)

    传送门:POJ 3764 题目大意: 在树上找一段路径(连续)使得边权相异或的结果最大. 前置技能: 1.用链式前向星建图. 2. 01字典树的应用. 思路: 本题用 vector数组建图是会超时的, ...

  4. 0x16.基本数据结构 — Trie树(字典树)+ A C 自 动 机

    目录 用TrieTrieTrie树来处理整数异或问题是真的舒服! 一.TrieTrieTrie树 TrieTrieTrie的基本操作 0.初始化 1.插入 2.检索 二.TrieTrieTrie树例题 ...

  5. Trie树(字典树)详细知识点及其应用

    Trie,又经常叫前缀树,字典树等等.它有很多变种,如后缀树,Radix Tree/Trie,PATRICIA tree,以及bitwise版本的crit-bit tree.当然很多名字的意义其实有交 ...

  6. 实现字典树(前缀树、Trie树)并详解其应用

    今天看到一个比较好的数据结构,字典树,做一下记录,以供自己后期复习和读者朋友的参考. 1.定义 字典树又称单词查找树.前缀树.Trie树等,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序 ...

  7. 【转】从Trie树(字典树)谈到后缀树

    本文第一部分,咱们就来了解这个Trie树,然后自然而然过渡到第二部分.后缀树,接着进入第三部分.详细阐述后缀树的构造方法-Ukkonen. 第一部分.Trie树 1.1.什么是Trie树 Trie树, ...

  8. 从Trie树(字典树)和后缀树

    从Trie树(字典树)谈到后缀树 转载:http://blog.csdn.net/v_july_v/article/details/6897097#t22 感谢作者,侵删. 引言 常关注本blog的读 ...

  9. trie(字典树、前缀树)

    trie(字典树.前缀树) 1. trie原理 原理 trie树,又被称为字典树.前缀树,是一种高效地存储和查找字符串集合的数据结构. 一般来说,用到trie的题目中的字母要么全是小写字母,要么全是大 ...

最新文章

  1. 如何首次在 Exchange Server 2003 SP1 上部署 RPC over HTTP
  2. 成为优秀程序员的十个Tips
  3. Git 提示fatal: remote origin already exists 错误解决办法
  4. 数据库常考面试知识点
  5. linux C++ 多线程使用pthread_cond 条件变量
  6. Objective-C中的instancetype和id关键字
  7. 需求分析挑战之旅(疯狂的订餐系统)(8)——最后的疯狂
  8. 学习笔记--2014年7月7日
  9. 基于OK6410开发板Uboot源码简单分析
  10. 浅谈对称加密和非对称加密
  11. “rt.jar is not on its project's build path”
  12. 快捷键 自动调整顺序_关于代码自动补全快捷键无法使用的新解决方案
  13. Flutter业务开发常用小技巧(样式布局篇)
  14. 计算机统考模拟系统3.0,统考计算机模拟系统操作流程
  15. 树莓派 引脚及接口图 AV接口顺序
  16. 微信小程序会议管理+后台管理系统
  17. Wise Force Deleter强制删除工具
  18. 下午茶,几个笑话提提神
  19. php unlink 无法删除,php unlink 删除问题
  20. 企业微信根据微信联系人批量自动发送邀请,还可根据手机号批量添加

热门文章

  1. 如何配置windows下的snmp服务
  2. vivado----fpga硬件调试 (五) ----找不到ila核问题及解决
  3. EIRP/ERP(有效辐射功率)基本概念
  4. linux 找回gpt分区,linux – 修复graid mini磁盘上损坏的GPT分区
  5. etcd 日志压缩_etcd集群备份和数据恢复以及优化运维
  6. github使用教程及小问题
  7. linux grep find查找文件夹、代码中的某行/字符串
  8. CosmoMC第一次测试
  9. python中异常的姓名
  10. python-docx官方声明