E. Short Code
time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

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.

Input

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.

Output

Print a single integer — the minimum possible total length of new variable names.

Examples
input

Copy
3
codeforces
codehorses
code
output

Copy
6
input

Copy
5
abba
abb
ab
aa
aacada
output

Copy
11
input

Copy
3
telegram
digital
resistance
output

Copy
3
Note

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的更多相关文章

  1. CodeForces - 965E Short Code

    Discription Arkady's code contains nn variables. Each variable has a unique name consisting of lower ...

  2. CodeForces 582A【multiset使用样例】

    题意: 给一些无序的数字,求解一个矩阵,使得矩阵的每一个元素都是行和列标志数的gcd,输出行标志数. 首先对数字进行排序.复杂度n*log(n^2). 这题的证明有官方的英文题解==在这直接贴英文题解 ...

  3. Codeforces 965E Short Code 启发式合并 (看题解)

    Short Code 我的想法是建出字典树, 然后让后面节点最多的点优先向上移到不能移为止, 然后gg. 正确做法是对于当前的节点如果没有被占, 那么从它的子树中选出一个深度最大的点换到当前位置. 用 ...

  4. trie树 Codeforces Round #367 D Vasiliy's Multiset

    // trie树 Codeforces Round #367 D Vasiliy's Multiset // 题意:给一个集合,初始有0,+表示添加元素,-去除元素,?询问集合里面与x异或最大的值 / ...

  5. 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 ...

  6. 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 ...

  7. 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 ...

  8. codeforces 706D D. Vasiliy's Multiset(trie树)

    题目链接: D. Vasiliy's Multiset time limit per test 4 seconds memory limit per test 256 megabytes input ...

  9. Codeforces #367 (Div. 2) D. Vasiliy's Multiset (trie 树)

    http://codeforces.com/group/1EzrFFyOc0/contest/706/problem/D 题目:就是有3种操作 + x向集合里添加 x - x 删除x元素,(保证存在 ...

随机推荐

  1. assert.notEqual()

    浅测试,使用不等于比较运算符(!=)比较. const assert = require('assert'); assert.notEqual(1, 2); // OK assert.notEqual ...

  2. 19Spring返回通知&异常通知&环绕通知

    在前置通知和后置通知的基础上加上返回通知&异常通知&环绕通知 代码: package com.cn.spring.aop.impl; //加减乘除的接口类 public interfa ...

  3. Python之面向对象继承和派生

    Python之面向对象继承和派生 什么是继承: 继承是一种创建新的类的方法.在Python中,新建的类可以继承自一个或多个父类.原始类称为基类或超类. 新建的类称为派生类或子类. Python中类的继 ...

  4. uva 12096 The SetStack Computer(STL set的各种库函数 交集 并集 插入迭代器)

    题意: 有5种操作: PUSH:加入“{}”空集合入栈. DUP:栈顶元素再入栈. UNION:出栈两个集合,取并集入栈. INTERSECT:出栈两个集合,取交集入栈. ADD:出栈两个集合,将先出 ...

  5. python之GUI图形用户界面 2014-4-7

    #图形用户界面1.下载和安装wxPython2.创建并显示一个框架import wx #导入wxPythonapp=wx.App()win=wx.Frame(None)win.Show() #调用窗口 ...

  6. c语音 dll断点调试方法

    转自:https://blog.csdn.net/qingzai_/article/details/45348613 dll调试方法: 1.把最新生成的dll和pdb放到 启动这个dll 的进程目录下 ...

  7. 全文搜索(A)-相关性

    文章:搜索相关性 文章:推荐系统中相似度算法介绍及效果测试 文章:常用的相似度计算方法原理及实现 文章:推荐系统用户相似度计算方法研究

  8. 【bzoj1965】[Ahoi2005]SHUFFLE 洗牌 - 快速幂

    为了表彰小联为Samuel星球的探险所做出的贡献,小联被邀请参加Samuel星球近距离载人探险活动. 由于Samuel星球相当遥远,科学家们要在飞船中度过相当长的一段时间,小联提议用扑克牌打发长途旅行 ...

  9. msp430入门编程10

    msp430中C语言操作端口I/O10 msp430中C语言的模块化头文件及实现11 msp430中C语言的模块化头文件及库文件12 msp430入门学习 msp430入门编程

  10. codevs——2750 心系南方灾区

    2750 心系南方灾区  时间限制: 1 s  空间限制: 2000 KB  题目等级 : 青铜 Bronze 题解  查看运行结果     题目描述 Description 现在我国南方正在承受百年 ...