题意
有N个字符串,要求你给出一个字典序,使它们按字典序排序后的结果和输入顺序一样。
思路
显然对于一个字符串i优先于字符串j,i的第一个和j不同的字母优于j的对应的字母。(若找不到该字母,即i是j的前面一部分则可以直接判断无解)
那么我们可以得到很多对字母之间的优先顺序,要给出26个字母的优先顺序,无非就是拓扑排序。
采用无前驱的顶点优先BFS的拓扑排序,如果存在没有被拓扑排序所排序到的节点,那么无解(即有环)。
发现没有特殊情况。
因为点少,用邻接矩阵建图。
code
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int maxn=110;
int n;
queue<int>q;
char s[maxn][maxn],ans[maxn];
bool link[30][30];
int in[maxn];
//无前驱的顶点优先bfs
bool bfs(){
int cnt=0;
for(int i=0;i<26;i++){
if(in[i]==0){ //先将入度为0的结点入队列
q.push(i);
ans[cnt++]='a'+i;
}
}
while(!q.empty()){
int now=q.front();
q.pop();
for(int i=0;i<26;i++){
if(link[now][i]){
in[i]--;
if(in[i]==0){
q.push(i);
ans[cnt++]='a'+i;
}
}
}
}
ans[26]='\0';
if(cnt<26) return false;
else return true;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=0;i<n;i++)
cin>>s[i];
bool flag=false;
for(int i=0;i<n-1;i++){
int len1=strlen(s[i]),len2=strlen(s[i+1]);
int ok=0;
for(int j=0;j<len1&&j<len2;j++){
if(s[i][j]!=s[i+1][j]){
ok=1;
int u=s[i][j]-'a',v=s[i+1][j]-'a';
if(!link[u][v]){
link[u][v]=true;
in[v]++;
}
}
if(ok) break;
}
if(!ok&&len1>len2) flag=true; //判断是否满足字典序
if(flag) break;
}
if(flag)
cout<<"Impossible"<<endl;
else{
if(bfs())
cout<<ans<<endl;
else
cout<<"Impossible"<<endl;
}
return 0;
}
学如逆水行舟,不进则退
来源:CSDN
作者:一百个Chocolate
链接:https://blog.csdn.net/weixin_42429718/article/details/104100586