P3065 [USACO12DEC]First! G
题意描述
不错的一道题。
给你 \(N\) 个字符串,要求你求出可能的字典序最小的字符串。
对于 可能的最小的字符串,你可以任意排列 \(26\) 个字母,使得其字典序最小。
举个栗子:(好像就是样例)
4
omm
moo
mom
ommnom
首先明确一点:当一个单词为另一个单词的前缀时,较长的单词不可能为字典序最小的。
然后发现:
- 我们可以使用标准字母表使
mom
排在第一个。(即字典序最小) - 也可以使用字母表
abcdefghijklonmpqrstuvwxyz
使得omm
排在第一个。
就是酱紫。
算法分析
字符串让人联想到 \(trie\) 树,优先级关系让人联想到 拓扑排序,于是就解决了。
- 建立一颗 \(trie\) 树。(有需要的可以看看 trie 树学习笔记)
- \(dfs\),这个...很基础吧。
- 对于每一个字符串,建立一张有向图,利用 拓扑排序 判断其是否有环,无环就输出。
对于每一个字符串,我们可以设它的字典序是所有字符串中最小的。
也就是说,这个字符串的第 \(i\) 个字母 在 \(trie\) 的第 \(i\) 层(根节点算第 \(0\) 层)的所有字母中 字典序最小。
设这个字符串的第 \(i\) 个字母为 \(u\),我们可以连单向边 \(u \to v\),表示我们指定了 \(u\) 的字典序比 \(v\) 小。(其中 \(v\) 是第 \(i\) 层的其它字母)
根据题目描述里的粗体部分,当在遍历时已有字母为单词结尾(即有前缀)可以直接返回 false
。
当 \(26\) 个字母间的关系形成环时,也一定不能成为字典序最小的串。
代码实现
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<queue>
#define N 300010
using namespace std;
int n,trie[N][30],tot=1,ru[30],ans=0;
bool sum[N],flag[N],edge[30][30];
string s[N];
queue<int>q;
void insert(string x){
int p=1;
for(int i=0;i<x.size();i++){
int ch=x[i]-'a';
if(!trie[p][ch]) trie[p][ch]=++tot;
p=trie[p][ch];
}
sum[p]=true;
return;
}
void topo(){
while(!q.empty()) q.pop();
for(int i=0;i<26;i++) if(!ru[i]) q.push(i);
while(!q.empty()){
int now=q.front();
q.pop();
for(int i=0;i<26;i++){
if(edge[now][i])
if(!(--ru[i])) q.push(i);
}
}
return;
}
bool ask(string x){
int p=1;
memset(edge,false,sizeof(edge));
memset(ru,0,sizeof(ru));
for(int i=0;i<x.size();i++){
if(sum[p]) return false;
int ch=x[i]-'a';
for(int j=0;j<26;j++){
if(ch!=j && trie[p][j] && !edge[ch][j]){
++ru[j];edge[ch][j]=true;
}
}
p=trie[p][ch];
}
topo();
for(int i=0;i<26;i++)
if(ru[i]) return false;
return true;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
cin>>s[i];
insert(s[i]);
}
for(int i=1;i<=n;i++){
if(ask(s[i])){
ans++;flag[i]=true;
}
}
printf("%d\n",ans);
for(int i=1;i<=n;i++){
if(flag[i]) cout<<s[i]<<endl;
}
return 0;
}
结语
trie 树真是个好东西
完结撒花。
P3065 [USACO12DEC]First! G的更多相关文章
- [luogu P3065] [USACO12DEC]第一!First!
[luogu P3065] [USACO12DEC]第一!First! 题目描述 Bessie has been playing with strings again. She found that ...
- 洛谷P3065 [USACO12DEC]第一!First!(Trie树+拓扑排序)
P3065 [USACO12DEC]第一!First! 题目链接:https://www.luogu.org/problemnew/show/P3065 题目描述 Bessie一直在研究字符串.她发现 ...
- P3065 [USACO12DEC]第一!First!
题目描述 Bessie has been playing with strings again. She found that by changing the order of the alphabe ...
- Luogu P3065 [USACO12DEC]第一!First!【字典树/拓扑排序】By cellur925
题意:给你许多字符串,你可以改变字母序大小,问有哪些字符串可能成为字典序最小的字符串. 我们考虑把这些字符串都塞到\(trie\)树上.之后检索每一个字符串的时候,我们看和他同一层的地方是否有字符,如 ...
- [USACO12DEC]第一!First! (Trie树,拓扑排序)
题目链接 Solution 感觉比较巧的题啊... 考虑几点: 可以交换无数次字母表,即字母表可以为任意形态. 对于以其他字符串为前缀的字符串,我们可以直接舍去. 因为此时它所包含的前缀的字典序绝对比 ...
- Storyboards Tutorial 03
这一节主要介绍segues,static table view cells 和 Add Player screen 以及 a game picker screen. Introducing Segue ...
- 文件图标SVG
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink ...
- [bzoj3012][luogu3065][USACO12DEC][第一!First!] (trie+拓扑排序判环)
题目描述 Bessie has been playing with strings again. She found that by changing the order of the alphabe ...
- Milk Pumping G&Milk Routing S 题解
Milk Pumping G&Milk Routing S 双倍经验时间 洛谷P5837 [USACO19DEC]Milk Pumping G 洛谷P3063 [USACO12DEC]Milk ...
随机推荐
- 087 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 01 封装的概念和特点
087 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 01 封装的概念和特点 本文知识点:封装的概念和特点 说明:因为时间紧张,本人写博客过程中只是对 ...
- 080 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 05 单一职责原则
080 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 05 单一职责原则 本文知识点:单一职责原则 说明:因为时间紧张,本人写博客过程中只是 ...
- SPI应用 用SPI总线读取气压传感器SCP1000的数据
Using SPI to read a Barometric Pressure Sensor This example shows how to use the SPI (Serial Periphe ...
- for循环迭代可迭代对象
模仿for循环迭代可迭代对象,# for i in Iterable:# iterable >>> 迭代器.iterator# 可迭代对象 iterable# 迭代器.iterato ...
- Mybatis中进行批量更新(updateBatch)
更新多条数据,每条数据都不一样 背景描述:通常如果需要一次更新多条数据有两个方式,(1)在业务代码中循环遍历逐条更新.(2)一次性更新所有数据(更准确的说是一条sql语句来更新所有数据,逐条更新的操作 ...
- 实验二 C2C实践
实验二 C2C实践 [实验目的] 掌握网上购物的基本流程和C2C平台的运营 [实验条件] ⑴.个人计算机一台 ⑵.计算机通过局域网形式接入互联网. (3).奥派电子商务应用软件 [知识准备] 本实验 ...
- 网易新闻精彩评论集合(慢慢收集ing)
一.刚才在停车场看一男的开个Q7,怎么也停不进去.我迅速把车停好要过去帮忙,他死活不同意.我说,你刚也看见了我的停车技术了,肯定不能给你刮了.他干脆把窗户摇上了.如今的社会啊,人与人的互信程度为什么就 ...
- 一入Java深似海
Java的基础语法 一个java程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来写协同工作.下面简要介绍下类.对象.方法和实例变量的概念. 对象: 对象是一个类的实例,有状态和行为.例如 ...
- 编程福利:50本C语言电子书,你还怕没书看吗!
推荐适合编程新手入门的几本经典的C语言书籍. 1.<C程序设计语言> C语言之父的著作,被称为C语言的的圣经.全球最经典的C语言教程.这本书最大的特点是精炼.读起来不会觉得"啰嗦 ...
- redis 各种数据结构的encoding实现
redis 各种数据结构的encoding实现 Redis type命令实际返回的就是当前键的数据结构类型,它们分别是:string(字符串).hash(哈希).list(列表).set(集合).zs ...