题意:有一串我们不知道由什么字符组成的长度为n的字符串,现在给你m个提示,每次会提示未知字符串中的两个字符以及这两个在原串的长度,接着会有原串的相对位置子字符串。
让你还原出原来的串,如果还原不了,输出-1。
题解:因为我们能知道这些字符的前后关系。
这时拓扑排序就是解决这类问题的:经常用于完成有依赖关系的任务的排序。
它是先将依赖关系建好边,然后每次从入度为0的点开始扫,最后出来的就是原来的顺序。
每次给提示字符串中的相对位置字符建边。
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10;
vector<int> vec[N*30];
int indeg[N*30],num[30];
int main()
{
int n,m;
cin>>n>>m;
int ncase=m*(m-1)/2;
while(ncase--)
{
string op,t;
int len;
cin>>op>>len;
if(!len){
getchar();continue;
}
cin>>t;
///给提示字符串中的字符建边
int a=0,b=0,cur=0,id=0;
for(int i=0;i<len;i++)
{
if(t[i]==op[0]){
a++;
id=(t[i]-'a')*10000+a;
}
else{
b++;
id=(t[i]-'a')*10000+b;
}
if(cur){
indeg[id]++;
vec[cur].push_back(id);
}
cur=id;
}
num[op[0]-'a']=a;
num[op[1]-'a']=b;
}
///存放入度为0的点
queue<int> que;
for(int i=0;i<26;i++){
if(num[i]&&indeg[i*10000+1]==0)
que.push(i*10000+1);
}
string ans;
while(!que.empty()){
int top=que.front();
que.pop();
ans+=(char)((top-1)/10000+'a');
for(auto v: vec[top]){
indeg[v]--;
if(!indeg[v]){
que.push(v);
}
}
}
if(ans.size()!=n){
printf("-1\n");
}
else cout<<ans<<endl;
return 0;
}