codeforces 965E Trie+multiset
1 second
256 megabytes
standard input
standard output
Arkady's code contains nn variables. Each variable has a unique name consisting of lowercase English letters only. One day Arkady decided to shorten his code.
He wants to replace each variable name with its non-empty prefix so that these new names are still unique (however, a new name of some variable can coincide with some old name of another or same variable). Among such possibilities he wants to find the way with the smallest possible total length of the new names.
A string aa is a prefix of a string bb if you can delete some (possibly none) characters from the end of bb and obtain aa.
Please find this minimum possible total length of new names.
The first line contains a single integer nn (1≤n≤1051≤n≤105) — the number of variables.
The next nn lines contain variable names, one per line. Each name is non-empty and contains only lowercase English letters. The total length of these strings is not greater than 105105. The variable names are distinct.
Print a single integer — the minimum possible total length of new variable names.
3
codeforces
codehorses
code
6
5
abba
abb
ab
aa
aacada
11
3
telegram
digital
resistance
3
In the first example one of the best options is to shorten the names in the given order as "cod", "co", "c".
In the second example we can shorten the last name to "aac" and the first name to "a" without changing the other names.
题意:给出很多字符串(1e5),总长度不超过1e5.
每个字符串用其某前缀代替,代替后要保证每个字符串互不相同。
求代替后最短的总距离。
题解:
做法非常巧妙和套路
建个Trie树,每个节点维护深度和一个multiset用于存储深度(当前取得字符串前缀的长度)(也可以用priority_queue,这种做法明天补上)
初始时,叶节点的multiset存储该节点的深度,这个初始状态就是最差的情况,即每个字符串都保留原串,下面会在合并的时候进行统计和优化。
然后从根节点开始dfs,dfs回溯段合并子节点的multiset,合并之后,去掉multiset中的最大值,插入当前节点深度(意义就是将当前最长的前缀替换成当前节点所代表的前缀,这样贪心一定是最优的)。
最后遍历根节点的multiset就可以得到答案。
合并的复杂度是
这样的,根据主定理,就是mlogm
,multiset的操作的复杂度是logm,总复杂度是m*(logm)^2
合并之后一定要把子节点的multiset清空,不然会MLE。
/*
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◇◆◆◆◇◇◇◇◇
◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◆◆◇◇◇◇◇◇◇◇◇◇◆◆◆◆◆◇◇◇◇◇
◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◆◆◇◇◇◇◇◇◇◇◇◇◆◆◇◆◆◇◇◇◇◇
◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇◇◇◆◇◇◇◆◇◇◇◇◇
◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇◇◇◇◆◇◇◇◆◇◇◇◇◇
◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◇◆◇◇◇◇◇◇◇◇◇◇◆◇◇◇◆◇◇◇◇◇
◇◇◇◇◇◇◆◆◆◆◇◇◇◇◇◇◇◇◇◇◆◆◆◆◆◇◇◇◇◇◇◇◇◇◆◆◆◇◆◆◆◇◇◇◇
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<set>
#include<vector>
using namespace std;
int read(){
int xx=,ff=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')ff=-;ch=getchar();}
while(ch>=''&&ch<=''){xx=xx*+ch-'';ch=getchar();}
return xx*ff;
}
const int maxn=;
int N;
char str[maxn];
struct Trie{
int lin[];
int depth;
multiset<int>s;
}T[maxn];
int cnt=;
void insert(int depth,int root){
if(!str[depth]){
T[root].s.insert(T[root].depth);
return;
}
if(!T[root].lin[str[depth]-'a']){
T[root].lin[str[depth]-'a']=++cnt;
T[cnt].depth=T[root].depth+;
}
insert(depth+,T[root].lin[str[depth]-'a']);
}
void trav(int x){
bool flag=x&&T[x].s.empty();
for(int i=;i<;i++)
if(T[x].lin[i]){
trav(T[x].lin[i]);
if(T[x].s.size()<T[T[x].lin[i]].s.size())
swap(T[x].s,T[T[x].lin[i]].s);
for(multiset<int>::iterator it=T[T[x].lin[i]].s.begin();it!=T[T[x].lin[i]].s.end();it++)
T[x].s.insert(*it);
T[T[x].lin[i]].s.clear();
}
if(flag){
T[x].s.erase(--T[x].s.end());
T[x].s.insert(T[x].depth);
}
}
int main(){
//freopen("in","r",stdin);
N=read();
for(int i=;i<=N;i++){
gets(str);
insert(,);
}
trav();
long long ans=;
for(multiset<int>::iterator it=T[].s.begin();it!=T[].s.end();it++)
ans+=(*it);
printf("%I64d\n",ans);
return ;
}
codeforces 965E Trie+multiset的更多相关文章
- CodeForces - 965E Short Code
Discription Arkady's code contains nn variables. Each variable has a unique name consisting of lower ...
- CodeForces 582A【multiset使用样例】
题意: 给一些无序的数字,求解一个矩阵,使得矩阵的每一个元素都是行和列标志数的gcd,输出行标志数. 首先对数字进行排序.复杂度n*log(n^2). 这题的证明有官方的英文题解==在这直接贴英文题解 ...
- Codeforces 965E Short Code 启发式合并 (看题解)
Short Code 我的想法是建出字典树, 然后让后面节点最多的点优先向上移到不能移为止, 然后gg. 正确做法是对于当前的节点如果没有被占, 那么从它的子树中选出一个深度最大的点换到当前位置. 用 ...
- trie树 Codeforces Round #367 D Vasiliy's Multiset
// trie树 Codeforces Round #367 D Vasiliy's Multiset // 题意:给一个集合,初始有0,+表示添加元素,-去除元素,?询问集合里面与x异或最大的值 / ...
- Codeforces Round #367 (Div. 2) D. Vasiliy's Multiset Trie
题目链接: http://codeforces.com/contest/706/problem/D D. Vasiliy's Multiset time limit per test:4 second ...
- Codeforces Round #367 (Div. 2) D. Vasiliy's Multiset(可持久化Trie)
D. Vasiliy's Multiset time limit per test 4 seconds memory limit per test 256 megabytes input standa ...
- Codeforces Round #367 (Div. 2) D. Vasiliy's Multiset trie树
D. Vasiliy's Multiset time limit per test 4 seconds memory limit per test 256 megabytes input standa ...
- codeforces 706D D. Vasiliy's Multiset(trie树)
题目链接: D. Vasiliy's Multiset time limit per test 4 seconds memory limit per test 256 megabytes input ...
- Codeforces #367 (Div. 2) D. Vasiliy's Multiset (trie 树)
http://codeforces.com/group/1EzrFFyOc0/contest/706/problem/D 题目:就是有3种操作 + x向集合里添加 x - x 删除x元素,(保证存在 ...
随机推荐
- Python之禅 吾心笃定
自从3月19日到现在已经学习python 19天了,博客园也注册8天了.之所以一直没有急着分享学习中的知识是因为我觉得学习一道应该从心开始,所以第一篇随笔不应该说python的知识,而应该说学习心态和 ...
- wepy 编译警告去除办法
如果你用过wepy打包小程序的话,那么你一定碰到了很多坑,(什么也不用说,抱一下吧)下面记录的是本人遇到的一个小坑, 编译的时候出现了黄色警告 如果你出现了上图这样的话,相信你一定也知道什么意思,就是 ...
- web应用无法访问的原因之一以及如何设置数据库编码
这篇随笔,本是应该是在前天晚上发的,但是因为事情太多,硬生生拖到了现在,当时,在我将web应用部署到服务器上时,在调用接口时,客户端没有任何反应,应该是又出异常了,查看了控制台的异常输出,提示requ ...
- 集训第六周 数学概念与方法 J题 数论,质因数分解
Description Tomorrow is contest day, Are you all ready? We have been training for 45 days, and all g ...
- NOI模拟(3.3)螺旋序列(出题人一定是月厨)
Description S也想寻求真正的智慧,然而由于“抑制力”的存在,她必须先解决一系列询问.有一个长度为n的序列a,一个长度为m序列b被称为螺旋序列当且仅当b1=bm且对于1<=i<= ...
- Orcad中较好的习惯背景
设置背景,能让眼睛不那么疲劳,尤其是白色背景,有的时候很耀眼,看的时间长了,眼疼. 因此萌生出更换背景的想法: Option->Preference中 第一列的Prin中"Alias& ...
- PCB中贴片元器件的引脚规范(allegro)
表贴的芯片一个引脚焊盘的宽度: 当芯片引脚间的间距>=26mil时,计算公式是(脚宽度+8mil) 当芯片引脚的间距<26mil时,计算公式是(引脚间距/2+1) 表贴的芯片一个引脚焊盘的 ...
- C51 使用端口 个人笔记
使用整个端口的8个引脚: 八个引脚,需要8位2进制,2位十六进制 #define P0 led led = 0x3f; //led = ~0x3f; 使用某个端口的某一个引脚 sbit led = P ...
- django2
八 Models 数据库的配置 1 django默认支持sqlite,mysql, oracle,postgresql数据库. <1> sqlite django默认使用sqlit ...
- DP 简单题目练习
ZOJ 1234 这道题目我表示也还不是特别能理解....还是太菜了T T 从后往前思考,因为只要后面有多的数在,那么C肯定是存在的,只要考虑是否把前两个数加在一起作为badness值这样两种情况来考 ...