1396:病毒(virus)

  • 白书最后一道题!加油!
  • 链接

分析

  • 由 题目所处的位置可判断要应用拓扑排序 (废话)
  • 难度主要在于如何比较字典序,注意比较相邻两单词第一个不相同的字母即可
  • 输出0的情况:
    1 存在环
    2 字典不完整(找不到对应字母)
#include <bits/stdc++.h>
using namespace std;
int n,tot;
int f[30],G[30][30],v[30],res[30],h[30];
//f记录入度,G记录前后,v记录是否入队,res中转,h记录对应顺序
string s[50010];
stack<int> r;
int main()
{
    memset(f,0x3f,sizeof(f));
    cin>>n;
    for(int i=1;i<=n;i++) cin>>s[i];
    for(int i=1;i<n;i++){
        if(s[i]==s[i+1]) //完全相同,下一个
			continue;
        if(s[i+1].find(s[i])==0) //后一个包含前一个,没有比较的意义
			continue;
        if(s[i].find(s[i+1])==0){//前一个包含后一个,字典错误(与上一个相反)
		    puts("0"); 
			return 0; 
		}
        int x=0;
        while(s[i][x]==s[i+1][x]) //寻找不同字母
			x++;
        int a=s[i][x]-'a'+1,b=s[i+1][x]-'a'+1;
        if(G[b][a]){ //这里a在b前,而之前b在a前,前后矛盾,字典错误,结束
		    puts("0"); 
			return 0; 
		}
        G[a][b]=1;//存储
        if(!v[a]) v[a]=1,f[a]=0;
        if(!v[b]) v[b]=1,f[b]=1;
        else f[b]++;//入度加一
    }
    memset(v,0,sizeof(v));
    for(int i=1;i<30;i++) 
		if(!f[i]) 
			r.push(i),v[i]=1;
    while(r.size()) {//拓扑排序
        int x=r.top(); r.pop();
        res[++tot]=x;//记录当前
        for(int i=1;i<30;i++) {
            if(G[x][i]) f[i]--;//入度减一
            if(!f[i]&&!v[i]) 
				r.push(i),v[i]=1;
        }
    }
    for(int i=1;i<=tot;i++) 
		h[res[i]]=i;
    string que,ans; //que是被感染的字符串,ans是答案
	cin>>que;
    for(int i=0;i<que.length();i++) {
        if(!h[que[i]-'a'+1]){//字典不完整,找不到对应字符
		    puts("0"); 
			return 0;
		}
        ans+=(char)(h[que[i]-'a'+1]+'a'-1);//记录答案
    }
    cout<<ans<<endl;
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值