病毒Virus

一本通P1396 病毒Virus

题目简述

给定\(k\)个被病毒感染了的字符串,知道这\(k\)个字符串原本是按字典序从小到大排列,最后给出一个待复原的字符串\(s\),要求根据上面的\(k\)个被感染的字符串复原\(s\)

  • 数据范围

\(k≤50000\)


所需算法

拓扑排序&模拟

前置知识

如果想了解拓扑排序欢迎来踩我的另一篇博客呀qvq


解题思路

感觉有点没读懂或者没思路?

那我们通过思考几个问题来找出思路:

  • \(k\)个被感染的字符串能为我们带来什么?

因为这\(k\)个字符串原本是按字典序排列的,所以是有序的;被病毒感染只会改变原来字符串的样子,但并不会影响原来的排序!

所以我们可以根据这\(k\)个字符串得出原字符\(x\)和感染后的字符\(y\)之间的对应关系!(可以理解为一一对应的映射关系)

  • 怎么找到这种映射关系?

这里我想到的做法是:双层循环+逐位查询+拓扑排序

说白点就是先模拟字典序排序的过程:如果两个字符串的第\(i\)位相等,则判断第\(i+1\)位,直到其中一个字符串完结

在这个过程中我们找到一个两个字符不同的位置,就进行连边和入度累加的操作,之后使用拓扑排序便能得到映射关系

  • 怎么想到的拓扑排序?

为了方便理解,我们插入理解一下样例:

  1. 先通过模拟字典序排序过程,我们可以得到如下的字符大小序列:\(c<e<d<a<b\) 和 \(e<a\)

  2. 那么映射关系即:\(c->a,e->b,d->c,a->d,b->e\)(注意箭头前的是被感染后的字符,箭头后的是原始字符)

找到了一个感觉没有?qwq

\(c<e<d<a<b\)这个即是拓扑序列!然后根据这个拓扑序列我们就能够找到映射关系!


代码Code

思路就是如上这么多了,理解后应该就能A掉这道题了,只是敲代码需要细心一点

现在先放出每个关键步骤的代码段(有注释),最后会放上完整的AC代码(无注释)

  • 模拟字典序排序
for(register int i=1;i<=n;i++) {  //循环1-n个字符串,这里的n相当于题目中的k(个人习惯啦qwq)
for(register int j=i+1;j<=n;j++) { //循环在i之后的字符串
int l=0; //l枚举字符串的位置
while(l<word[i].length()&&l<word[j].length()) { //匹配长度小于两个字符串的最小长度
flag[word[i][l]-'0']=1; //标记一下出现过,后面会用
if(word[i][l]==word[j][l]) l++; //相同则不管
else {
flag[word[j][l]-'0']=1;
in[word[j][l]-'0']++; //不同说明i串位置字符的字典序先于j串位置字符的字典序
add(word[i][l]-'0',word[j][l]-'0'); //连边+入度累加
break; //找到一位后面的就不用比较了
}
}
}
}
  • 拓扑排序
for(register char i='a';i<='z';i++) {  //如果这个字符出现过且入度为0(即字典序最先),就入队
if(flag[i-'0']==1&&in[i-'0']==0) q.push(i-'0');
}
while(!q.empty()) {
int x=q.front();
q.pop();
if(ans[x]!=0) { //这里是判断一个感染字符对应多个原始字符的错误情况
printf("0");
return 0;
}
ans[x]=sum; //注意ans是一个整型map
sum++;
for(register int i=head[x];i;i=e[i].net) { //遍历所有字典序在x之后的字符
int v=e[i].to;
in[v]--;
if(in[v]==0) q.push(v);
}
}
  • 完整代码
#include <bits/stdc++.h>
using namespace std;
queue<int> q;
map<int,int> ans;
string word[50002];
int n,tot,sum=97,in[201],head[201],flag[201]; struct node {
int to,net;
} e[50001]; inline void add(int u,int v) {
e[++tot].to=v;
e[tot].net=head[u];
head[u]=tot;
} int main() {
scanf("%d",&n);
for(register int i=1;i<=n;i++) {
cin>>word[i];
}
for(register int i=1;i<=n;i++) {
for(register int j=i+1;j<=n;j++) {
int l=0;
while(l<word[i].length()&&l<word[j].length()) {
flag[word[i][l]-'0']=1;
if(word[i][l]==word[j][l]) l++;
else {
flag[word[j][l]-'0']=1;
in[word[j][l]-'0']++;
add(word[i][l]-'0',word[j][l]-'0');
break;
}
}
}
}
cin>>word[n+1];
for(register char i='a';i<='z';i++) {
if(flag[i-'0']==1&&in[i-'0']==0) q.push(i-'0');
}
while(!q.empty()) {
int x=q.front();
q.pop();
if(ans[x]!=0) {
printf("0");
return 0;
}
ans[x]=sum;
sum++;
for(register int i=head[x];i;i=e[i].net) {
int v=e[i].to;
in[v]--;
if(in[v]==0) q.push(v);
}
}
for(register int i=0;i<word[n+1].length();i++) { //如果对应不完,那也是一种错误情况
if(ans[word[n+1][i]-'0']==0) {
printf("0");
return 0;
}
}
for(register int i=0;i<word[n+1].length();i++) {
cout<<char(ans[word[n+1][i]-'0']);
}
return 0;
}

病毒Virus的更多相关文章

  1. sublimeText jsformat 插件被当做病毒 virus

    最近在个只可往他里面发邮件,不能往外上任何互联网的地方工作,用 sublimetext 要装个sublime 插件 jsformat 十分麻烦.用gmail邮箱发总是报病毒. 最后挨个尝试,发现是 j ...

  2. 对病毒Virus.Win32.Ramnit.B的研究

  3. 最近碰到了一个病毒木马:virus.win32.ramnit.B

    由于 使用了 简单游 平台上的挂机工具: 番茄-自动人机对战免费版1217  ,使用了很久,头段时间家里电脑 360提示有病毒,本来我一直忽略的,但 我扫描了一下,大量的这个木马,于是 吧 简单游卸载 ...

  4. Web测试介绍2一 安全测试

            安全测试是在IT软件产品的生命周期中,特别是产品开发基本完成到发布阶段,对产品进行检验以验证产品符合安全需求定义和产品质量标准的过程. 主要安全需求包括: (i) 认证 Authent ...

  5. [A Top-Down Approach][第一章 计算机网络和因特网]

    [A Top-Down Approach][第一章 计算机网络和因特网] 标签(空格分隔): 计算机网络 介绍基本术语和概念 查看构成网络的基本硬件和软件组件. 从网络的边缘开始,考察在网络中运行的端 ...

  6. virus.win32.parite.H病毒的查杀方法

    virus.win32.parite.H病毒的查杀方法 昨天电脑中了virus.win32.parite.H病毒,搞了2个多小时最终搞定了.以下记录下我的解决方法. 第一步:下载Win32.Parit ...

  7. virus.win32.parite.H查杀病毒的方法

    virus.win32.parite.H病毒的查杀方法 昨天电脑中了virus.win32.parite.H病毒,搞了2个多小时最终搞定了.以下记录下我的解决方法. 第一步:下载Win32.Parit ...

  8. [LeetCode] Contain Virus 包含病毒

    A virus is spreading rapidly, and your task is to quarantine the infected area by installing walls. ...

  9. [Swift]LeetCode749. 隔离病毒 | Contain Virus

    A virus is spreading rapidly, and your task is to quarantine the infected area by installing walls. ...

随机推荐

  1. Java实现 LeetCode 622 设计循环队列(暴力大法)

    622. 设计循环队列 设计你的循环队列实现. 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环.它也被称为"环形缓冲器" ...

  2. Java实现 蓝桥杯VIP 算法提高 质因数2

    算法提高 质因数2 时间限制:1.0s 内存限制:256.0MB 将一个正整数N(1<N<32768)分解质因数,把质因数按从小到大的顺序输出.最后输出质因数的个数. 输入格式 一行,一个 ...

  3. Java实现 洛谷 P1980 计数问题

    import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = ...

  4. Java实现约瑟夫环问题

    约瑟夫环问题起源于一个犹太故事.约瑟夫环问题的大意如下: 罗马人攻占了桥塔帕特,41个人藏在一个山洞中躲过了这场浩劫.这41个人中,包括历史学家Josephus(约瑟夫)和他的一个朋友.剩余的39个人 ...

  5. java实现最大镜像子串

    ** 最大镜像子串** [代码填空](满分12分) 串"abcba"以字母"c"为中心左右对称:串"abba" 是另一种模式的左右对称.这两 ...

  6. 除了FastJson,你也应该了解一下Jackson(一)

    在上月末的时候收到一条关于fastjson安全漏洞的消息,突然想到先前好像已经有好多次这样的事件了(在fastjson上面).关于安全方面,虽然中枪的机率微小,但是在这个信息越来越复杂的时代,安全性也 ...

  7. 根据现有Bitmap生成相同图案指定大小的新Bitmap

    通过一张现有的Bitmap,画出一张同样的但是大小使我们指定的Bitmap 需求:直接createBitmap的话不允许生成的bitmap的宽高大于原始的,因此需要特定方法来将一张Bitmap的大小进 ...

  8. AbstractCollection类中的 T[] toArray(T[] a)方法源码解读

    一.源码解读 @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { //size为集合的大小 i ...

  9. 02-Python基础1

    本节内容 列表.元组操作 字符串操作 字典操作 集合操作 文件操作 字符编码与转码 1. 列表.元组操作 列表是我们最以后最常用的数据类型之一,通过列表可以对数据实现最方便的存储.修改等操作 定义列表 ...

  10. 用Java模拟游戏重力的实现(弹跳)

    年末开了Java实训大作业 想了好几天决定选择马里奥小游戏 发现即使做出来但是跳跃功能是很“笨拙”的,和我们玩的游戏不一样,没有跳跃速度的快慢什么的,后来才知道这个叫做游戏里面重力的模拟. 组队做系统 ...