Description

Lweb 面对如山的英语单词,陷入了深深的沉思,“我怎么样才能快点学完,然后去玩三国杀呢?”。这时候睿智
的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,他的计划册是长这样的:
—————
序号  单词
—————
 1
 2
……
n-2
n-1
 n
—————
然后凤老师告诉 Lweb ,我知道你要学习的单词总共有 n 个,现在我们从上往下完成计划表,对于一个序号为 x 
的单词(序号 1...x-1 都已经被填入):
1) 如果存在一个单词是它的后缀,并且当前没有被填入表内,那他需要吃 n×n 颗泡椒才能学会;
2) 当它的所有后缀都被填入表内的情况下,如果在 1...x-1 的位置上的单词都不是它的后缀,那么你吃 x 颗泡
椒就能记住它;
3) 当它的所有后缀都被填入表内的情况下,如果 1...x-1的位置上存在是它后缀的单词,所有是它后缀的单词中
,序号最大为 y ,那么你只要吃 x-y 颗泡椒就能把它记住。
Lweb 是一个吃到辣辣的东西会暴走的奇怪小朋友,所以请你帮助 Lweb ,寻找一种最优的填写单词方案,使得他
记住这 n 个单词的情况下,吃最少的泡椒。

Input

输入一个整数 n ,表示 Lweb 要学习的单词数。接下来 n 行,每行有一个单词(由小写字母构成,且保证任意单
词两两互不相同)1≤n≤100000, 所有字符的长度总和 1≤|len|≤510000

Output

Lweb 吃的最少泡椒数

Sample Input

2
a
ba

Sample Output

2

题目大意

给你$n$个字符串,不同的排列有不同的代价,代价按照如下方式计算(字符串$s$的位置为$x$):
1.排在$s$后面的字符串有$s$的后缀,则代价为$n^2$;
2.排在$s$前面的字符串有$s$的后缀,且没有排在$s$后面的$s$的后缀,则代价为$x-y$($y$为最后一个与$s$不相等的后缀的位置);
3.$s$没有后缀,则代价为$x$。
求最小代价和。

题解

我们将“后缀”转化为“前缀”,那么很显然这是一个可以在$Trie$树上解决的问题。

我们建完$Trie$树后,我们建立一个根节点$0$,发现其实答案就是所有节点的编号与其父亲节点的编号差值和。

这个结论是建立在$1$号情况不能出现的情况下,因为$1$号情况代价最大,我们显然必须避开,并且一定能够避开。

那么现在问题就变成了给你一棵树,让你给节点编号(父节点编号一定比子节点小),求所有节点的编号与其父亲节点的编号差值和最小值。

很容易得到的一个贪心策略是:每次选深度最小的子树先标号。

简要证明一下:因为对于一个子树,其内部最优值一定是不变的,影响答案的只有与当前节点相邻节点的编号关系。那么我们一定先选子树$size$小的先编号,一定能得到最优值。

那么$dfs$的时候我们要选最小的$size$,如何实现?我们可以开个栈来按顺序存储要访问的节点,就可以了。

 //It is made by Awson on 2017.10.10
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define sqr(x) ((x)*(x))
using namespace std;
const int M = ;
const int N = ; int n;
LL ans;
int trie[M+][], val[M+], pos;
char s[M+];
struct tt {
int to, next;
}edge[N+];
int path[N+], top;
int size[N+], vis[N+], tot;
struct ss {
int size, id;
bool operator < (const ss &b) const{
return size > b.size;
}
}tmp[N+];
stack<int>S; void add(int u, int v) {
edge[++top].to = v;
edge[top].next = path[u];
path[u] = top;
}
void dfs(int u, int last) {
++tot;
if (val[u]) add(last, val[u]), last = val[u];
for (int i = ; i < ; i++)
if (trie[u][i])
dfs(trie[u][i], last);
}
void insert(char *s, int len, int num) {
int u = ;
for (int i = len-; i >= ; i--) {
if (!trie[u][s[i]-'a']) trie[u][s[i]-'a'] = ++pos;
u = trie[u][s[i]-'a'];
}
val[u] = num;
}
void get_size(int u) {
size[u] = ;
for (int i = path[u]; i; i = edge[i].next) {
get_size(edge[i].to);
size[u] += size[edge[i].to];
}
}
void get_ans(int u, int fa) {
int pos = ; vis[u] = ++tot; ans += vis[u]-vis[fa];
for (int i = path[u]; i; i = edge[i].next) {
tmp[++pos].size = size[edge[i].to];
tmp[pos].id = edge[i].to;
}
sort(tmp+, tmp++pos);
for (int i = ; i <= pos; i++) S.push(tmp[i].id);
while(pos--) {
int v = S.top(); S.pop();
get_ans(v, u);
}
}
void work() {
scanf("%d", &n);
for (int i = ; i <= n ;i++) {
scanf("%s", s);
insert(s, strlen(s), i);
}
dfs(, );
get_size();
get_ans(, );
printf("%lld\n", ans);
}
int main() {
work();
return ;
}
 

[SCOI 2016]背单词的更多相关文章

  1. 做中学(Learning by Doing)之背单词-扇贝网推荐

    做中学(Learning by Doing)之背单词-扇贝网推荐 看完杨贵福老师(博客,知乎专栏,豆瓣)的「继续背单词,8个月过去了」,我就有写这篇文章的冲动了,杨老师说: 有时候我会感觉非常后悔,如 ...

  2. “我爱背单词”beta版发布与使用说明

    我爱背单词BETA版本发布 第二轮迭代终于画上圆满句号,我们的“我爱背单词”beta版本已经发布. Beta版本说明 项目名称 我爱背单词 版本 Beta版 团队名称 北京航空航天大学计算机学院  拒 ...

  3. BZOJ4567[Scoi2016]背单词

    4567: [Scoi2016]背单词 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 304 Solved: 114 [Submit][Status] ...

  4. 《我爱背单词》 Alpha版 发布说明

    ——发布地址(baidu网盘) http://pan.baidu.com/s/15omtB ——简介  <我爱背单词>是一款英语单词记忆和管理辅助软件,旨在帮助广大考生在短期内攻克GRE. ...

  5. [No000057]一个人默默背单词,小心被传染哦

    不日凛冬将至,全国各地,已有多名少侠因季节变化,出现了不同程度的四肢不勤.bd不分的症状.具体表现为—— 包大人在此高能预警:不想背单词,有可能你已经被传染了. 好好的,怎么突然不想背单词了 哈佛医学 ...

  6. [No000014]听说不背单词,考英语会是这种下场-我们为什么必须背单词?

    由于英语对于一个程序员来说,重要性你懂得.因此我会开始逐渐在博客上加入英语的一些东西. 听说不背单词,考英语会是这种下场 在中国, 「学英语」大抵遵循着这样一条 罗蒙诺索夫质量守恒定律 因为英语学着学 ...

  7. Supermemo背单词7周年纪念

    从2007年2月1日开始,用Supermemo背单词7周年了,在2013年11月21日将单词表Reset,重新开始Review以前背过的单词,并慢慢加入听写VOA时遇到的生词.

  8. 使用Excel背单词-高效-简单

    背单词是一个很纠结的事,想必那些走在留学路上的很多人都被英语这一关卡住了,这里,笔者就聊聊,不讲背单词的方法,只提供使用vb开发的产品和使用方法,有问题欢迎讨论. 简介:使用excel背单词,有一些人 ...

  9. 基于百词斩和扇贝单词的背单词APP软件测试

    概述 背单词APP是非常受大学生青睐的手机应用,但它的发展尚未成熟,存在一些缺陷.我们决定深入地分析一组典型的背单词APP:百词斩(A产品).扇贝单词(B产品),寻找当前背单词APP中的提升空间.下面 ...

随机推荐

  1. 2018.3.29 DIV位置调整代码

    <!DOCTYPE html><html>    <head>        <meta charset="UTF-8">      ...

  2. Beta 第三天

    今天遇到的困难: 组员对github极度的不适应 github的版本控制和协同化编程确实操作起来需要一定的熟练度,我们缺乏这种熟练度 Android Studio版本不一致项目难以打开的问题仍然无法解 ...

  3. C语言第五次博客作业

    一.PTA实验作业 题目1:6-6 使用函数输出水仙花数 1. 本题PTA提交列表 2. 设计思路 (1) 首先先定义narcissistic函数. (2)定义四个整形变量n,a,d,cnt,sum, ...

  4. 201621123057 《Java程序设计》第12周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 面向系统综合设计-图书馆管理系统或购物车 使用流与文件改造你的图书馆管理系统或购物车. 2.1 简述如何 ...

  5. python array 使用创建10万浮点数

    from array import array from random floats = array('d',random((for i in range(10**7)) fp = open('flo ...

  6. 第十二条:考虑实现Comparable接口

    与前面讨论的方法不同,compareTo()方法并没有在Object类中定义.相反,它是Comparable接口中唯一的方法. 一个类的实例对象要想是可以比较大小的,那么这个类需要实现Comparab ...

  7. UVA 10622 Perfect P-th Powers

    https://vjudge.net/problem/UVA-10622 将n分解质因数,指数的gcd就是答案 如果n是负数,将答案除2至奇数 原理:(a*b)^p=a^p*b^p #include& ...

  8. Python设计TFTP客户端

    #coding=utf-8 from socket import * from threading import Thread import struct def recvData(fileName, ...

  9. maven入门(6)maven的生命周期

    1. 三套生命周期     Maven拥有三套相互独立的生命周期,它们分别为clean,default和site. 每个生命周期包含一些阶段,这些阶段是有顺序的,并且后面的阶段依赖于前面的阶段,用户和 ...

  10. Dijkstra的双栈算术表达式求值算法

    这次来复习一下Dijkstra的双栈算术表达式求值算法,其实这就是一个计算器的实现,但是这里用到了不一样的算法,同时复习了栈. 主体思想就是将每次输入的字符和数字分别存储在两个栈中.每遇到一个单次结束 ...