1396:病毒(virus)

【题目描述】

一天,小y突然发现自己的计算机感染了一种病毒!还好,小y发现这种病毒很弱,只是会把文档中的所有字母替换成其它字母,但并不改变顺序,也不会增加和删除字母。

现在怎么恢复原来的文档呢!小y很聪明,他在其他没有感染病毒的机器上,生成了一个由若干单词构成的字典,字典中的单词是按照字母顺序排列的,他把这个文件拷贝到自己的机器里,故意让它感染上病毒,他想利用这个字典文件原来的有序性,找到病毒替换字母的规律,再用来恢复其它文档。

现在你的任务是:告诉你被病毒感染了的字典,要你恢复一个字母串。

【输入】

第一行为整数K(≤50000),表示字典中的单词个数。

以下K行,是被病毒感染了的字典,每行一个单词。

最后一行是需要你恢复的一串字母。

所有字母均为小写。

【输出】

输出仅一行,为恢复后的一串字母。当然也有可能出现字典不完整、甚至字典是错的情况,这时请输出一个0。

【输入样例】

6
cebdbac
cac
ecd
dca
aba
bac
cedab

【输出样例】

abcde

代码:

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <map> 
#include <algorithm>
#define MAXN 50005
using namespace std;
 
int n , cnt ;
int in[MAXN] , ans[MAXN] ;
bool flag ;
char have[MAXN] ;
string s[MAXN] , g ;
vector <int> G[MAXN] ;
map <char , int > T ;
 
void Topol() {
	int count = 0 ;
	int k = 0 ;
	queue <int> q ;
	for( int i = 1 ; i <= cnt ; ++ i )
		if( !in[i] ) {
			k ++ ;
			q.push(i) ;
		}
	if( k != 1 ) {//拓扑序唯一
		flag = 1 ;
		return ;
	}
	while( !q.empty() ) {
		int sum = 0 ;
		int x = q.front() ;
		q.pop() ;
		count ++ ;
		ans[x] = count ;
		for( int i = 0 ; i < G[x].size() ; ++ i ) {
			int s = G[x][i] ;
			in[s] -- ;
			if( !in[s] ) {
				q.push(s); 
				sum ++ ;
			}
		}
		if( sum > 1  ) {//保证拓扑序唯一
			flag = 1 ;
			return ;
		}
	}
	if( count != cnt )//拓扑跑完了的
		flag = 1 ;
	return ;
}
 
int main() {
	scanf("%d", &n );
	for( int i = 1 ; i <= n ; ++i )
		cin >> s[i] ;
	cin >> g ;
	for( int i = 2 ; i <= n ; ++ i ) {
		for( int j = 0 ; j < min( s[i].length() , s[i-1].length() ) ; ++j ) {
			if( !T[s[i][j]] ) {//map存储
				cnt ++ ;
				T[s[i][j]] = cnt ;
				have[cnt] = s[i][j] ;//记录出现了的字母
			}
			if( !T[s[i-1][j]] ) {
				cnt ++ ;
				T[s[i-1][j]] = cnt ;
				have[cnt] = s[i-1][j] ;
			}
			if( s[i-1][j] != s[i][j] ) {//连边
				int a = T[s[i-1][j]] ;
				int b = T[s[i][j]] ;
				G[a].push_back(b) ;
				in[b] ++ ; 
				break ;
			}
		}
	}
	Topol();
	if( flag ) {
		printf("0");
		return 0;
	}
	sort( have+1 , have+cnt+1 );//排序
	for( int i = 0 ; i < g.length() ; ++ i ) {//是否有没出现的字母
		int now = T[g[i]];
		if( now == 0 ) {
			printf("0");
			return 0;
		}
	}
	for( int i = 0 ; i < g.length() ; ++ i ) {//找正确的字母
		int now = T[g[i]];
		int rig = ans[now] ;
		printf("%c", have[rig] );
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值