洛谷P3294 [SCOI2016]背单词——题解
阅读理解题题意解释可以看这位大佬的博客。
发现求后缀与倒序求前缀是等价的,而找前缀自然就想到了trie树。将所有字符串翻转后再建入trie树中,再对每一个字符串翻转后从trie树中找前缀,就能找到一个字符串的所有后缀了。
由第三种情况知我们要想最小化总代价,则最小化一个字符串与最靠近它的后缀间的距离应该也是一个要考虑的因素。其实一个串最近的后缀其实一定是它的所有后缀中长度最大的,因为它的后缀中长度短的也一定是长度大的后缀,并且还要避免第一种情况的出现(即序列在一个字符串后面的串中不能有这个字符串的后缀)。故我们只要知道每个字符串最长的后缀就好。若一个串是另一个串的后缀,则可以从这个串向另一个串连一条有向边,则最终会形成一个森林。
这时避免了第一种情况后,还有两种情况。我们做了这么多题,知道一种情况总应该比多种情况好做。故考虑将两种情况转化为一种。发现如果我们在所有题目给出的字符串的基础上再加入一个处于序列第0个位置的空串,那么第二种情况也就转化为了第三种情况,并且对答案没有影响。这种转化对于当前的森林,只要再建个标号为0的空串节点连向所有树的根就好了。
此时问题就转化为:给树的节点编号,要求父亲节点的序号比儿子节点小,且根节点的序号为0,并使得儿子节点的编号减父亲节点编号的差的和最小,求最小的和。考虑怎么选点编号。作者一开始也懵的一逼于是看了看这位大佬博客关于选法的证明部分(“考虑建出……Q.E.D”)终于明白如果选到了一个点,就要一口气把它的子树都选了,并且优先选子树大小最小的儿子。dfs就搞定了呀。至于对某个点的儿子从子树大小小的往大的选,可以用堆维护。
具体实现请看代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue> #define max(a,b) ((a)>(b)?(a):(b)) using namespace std; const int N=,LEN=; int tree[][],cnt,n,l,dfs;
int ed[LEN],in[N],lst[N],to[N],nxt[N],ecnt,dfn[N]; long long siz[N],ans; string word[N]; char ch; inline int read()
{
int x=;
ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=(x<<)+(x<<)+(ch^),ch=getchar();
return x;
} inline void getstring(string &a)
{
a="";
ch=getchar();
while(ch<'a'||ch>'z')
ch=getchar();
while(ch>='a'&&ch<='z')
a+=ch,ch=getchar();
} inline void insert(const string &a,int j)
{
l=a.length();
int now=,num;
for(int i=l-;i>=;--i)//要将字符串倒序插入trie树中
{
num=a[i]-'a';
if(!tree[now][num])
tree[now][num]=++cnt;
now=tree[now][num];
}
ed[now]=j;
} inline void addedge(int u,int v)
{
nxt[++ecnt]=lst[u];
lst[u]=ecnt;
to[ecnt]=v;
} inline int fin(const string &a)
{
int now=,num,ret=-;
l=a.length();
for(int i=l-;i>=;--i)//查后缀就是倒序查前缀
{
num=a[i]-'a';
if(!tree[now][num])
return ret;
now=tree[now][num];
if(ed[now]&&i)
ret=ed[now];
}
return ret;
} void dfssiz(int u)
{
siz[u]=;
for(int e=lst[u];e;e=nxt[e])
{
dfssiz(to[e]);
siz[u]+=siz[to[e]];
}
} struct node{
int lar,ord;
}head; inline bool operator < (const node &a,const node &b)
{
return a.lar>b.lar;//大根堆变小根堆
} void dfsans(int u)
{
priority_queue<node>hep;
for(int e=lst[u];e;e=nxt[e])
{
hep.push((node){siz[to[e]],to[e]});
}
while(!hep.empty())
{
head=hep.top();
hep.pop();
dfn[head.ord]=++dfs;//编号过程
ans+=dfn[head.ord]-dfn[u];
dfsans(head.ord);
}
} int main()
{
n=read();
for(int i=;i<=n;++i)
{
getstring(word[i]);//字符串的读入优化
insert(word[i],i);
}
int u;
for(int i=;i<=n;++i)
{
u=fin(word[i]);
if(u!=-)
{
addedge(u,i);
in[i]++;
}
}
for(int i=;i<=n;++i)
if(!in[i])//没有入度的点就是森林中树的根
addedge(,i);
dfssiz();//求一下每个点的子树大小。
dfsans();//统计答案。
printf("%lld",ans);
return ;
}
AC代码
洛谷P3294 [SCOI2016]背单词——题解的更多相关文章
- P3294 [SCOI2016]背单词
P3294 [SCOI2016]背单词 Trie+贪心 倒插进树+取出重建+子树处理+贪心遍历 倒插进树:把后缀转化为前缀,所以把字符串倒着插进Trie中 取出重建:重新建立一棵以单词为节点的树,如果 ...
- [SCOI2016]背单词 题解
背单词 https://www.luogu.com.cn/problem/P3294 前言: Trie树的省选题(瑟瑟发抖QAQ) 问题汇总:(请忽略) (1)对Trie字典树的运用不熟练 (2)没想 ...
- BZOJ4567:[SCOI2016]背单词——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4567 Lweb 面对如山的英语单词,陷入了深深的沉思,“我怎么样才能快点学完,然后去玩三国杀呢?” ...
- [luogu] P3294 [SCOI2016]背单词 (贪心)
题目描述 Lweb 面对如山的英语单词,陷入了深深的沉思,"我怎么样才能快点学完,然后去玩三国杀呢?".这时候睿智的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,他 ...
- 洛谷P3295 [SCOI2016]萌萌哒 题解
洛谷P3295 [SCOI2016]萌萌哒 题目描述 公式粘过来就乱了,还是去洛谷看题吧 分析 如果暴力解决的话就是使用并查集把位数相同的数位并在一起.比如区间[1,2]和区间[3,4]的数字完全相同 ...
- BZOJ4567[Scoi2016]背单词
4567: [Scoi2016]背单词 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 304 Solved: 114 [Submit][Status] ...
- 【BZOJ4567】[Scoi2016]背单词 Trie树+贪心
[BZOJ4567][Scoi2016]背单词 Description Lweb 面对如山的英语单词,陷入了深深的沉思,“我怎么样才能快点学完,然后去玩三国杀呢?”.这时候睿智 的凤老师从远处飘来,他 ...
- 【bzoj4567】[Scoi2016]背单词
4567: [Scoi2016]背单词 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1123 Solved: 476[Submit][Status][ ...
- 洛谷P1783 海滩防御 分析+题解代码
洛谷P1783 海滩防御 分析+题解代码 题目描述: WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和 ...
随机推荐
- JAVAEE 7 api.chm
JAVAEE 7 api.chm 链接:https://pan.baidu.com/s/1LUD3oam5B-Hp8tdpfQYk2w 提取码:x1kc
- AppCan模拟器调试
来源: 1, 页面CSS调试 2, JS调试 3, 插件请打包后手机调试 4, 打开另一个页面示例: appcan.button("#myBtn", "ani-uct&q ...
- JavaSE--异常机制
异常就是程序在运行时出现的不正常情况.发生在运行时期,java程序在运行时期发生的不正常情况,此时java就按照面向对象的思想对不正常现象进行描述和对象的封装.异常的由来:问题也是现实生活中一个具体的 ...
- Vue2.X 通过 ajax 获取 API 数据(非 axios)
不多废话,笔记如下 1. javascript: let vm = new Vue({ el: '#card-text', data: { info: '' }, beforeCreate: func ...
- jq上滑加载更多
html 结构 <div id="main"> <ul class="order-list" id="list_box"& ...
- dubbo学习笔记四(异步调用)
相关资料 官方文档 项目结构 代码示例 [EchoTestApp] @RestController @SpringBootApplication @ImportResource("class ...
- 第95:PCA
输入数据矩阵->计算每条记录的平均值和标准差->计算协方差矩阵->得到协方差矩阵的所有特征值和特征向量->对特征值进行从大到小的排序,并且得到与之对应的特征向量 PCA是无监督 ...
- mysql数据库表名区分大小写
使用mysql的时候,创建的表明都是大写的,但是查询语句中表明用消息就会报错,表不存在. 查询后发现mysql默认配置是表明区分大小写的,如果要修改成不区分大小写,需要修改一下配置. 1.修改MySq ...
- 常见shell用法
分析nginx访问日志 awk '{a[b[$1]++]}END{for(i=length(a);i>0;i--)for(j in b)if(b[j]==i){c++;if(c<=10)p ...
- Efficient Estimation of Word Representations in Vector Space (2013)论文要点
论文链接:https://arxiv.org/pdf/1301.3781.pdf 参考: A Neural Probabilistic Language Model (2003)论文要点 https ...