-
题意:给出一个长度n,一共m*(m-1)/2次查询,每次查询给出一些字母在字符串中的位置和个数,问根据这些字符位置能否构成一个符合要求的长度为n的字符串
-思路:给每一个字母编号,然后根据给出的顺序建图,求其拓扑排序,若能构成则证明存在这个字符串 -
核心技能:拓扑排序,参考博客
-
核心代码:
for(i=0;i<=260000;i++){
if(is[i]&&!dis[i]) q.push(i);
}
while(!q.empty()){
int now=q.front();
ans.push_back(now);
q.pop();
for(i=0;i<v[now].size();i++){
if(--dis[v[now][i]]==0) {
q.push(v[now][i]);
}
}
}
if(ans.size()==n) {
for(i=0;i<ans.size();i++){
printf("%c",(ans[i]/10000)+'a');
}
}
else{
printf("-1\n");
}
- 代码:
#include<bits/stdc++.h>
using namespace std;
char s[10005];
char t[10005];
vector<int> v[1000005];
int num[30];
int vl[10005];
int dis[1000005];
int is[1000005];
vector<int> ans;
queue<int> q;
int main(){
int i,j,n,m;
scanf("%d %d",&n,&m);
m=m*(m-1)/2;
for(i=0;i<m;i++){
int k;
scanf("%s %d",s,&k);
if(k!=0){
scanf("%s",t);
for(j=0;j<k;j++){
int h=t[j]-'a';
vl[j]=h*10000+num[h];
is[vl[j]]=1;
num[h]++;
}
for(j=0;j<k;j++){
int h=t[j]-'a';
if(j!=0){
dis[vl[j]]++;
}
if(j!=k-1){
//printf("%d %d\n",(t[j]-'a')*10000+num[h],(t[j+1]-'a')*10000 + num[t[j+1]-'a']+1);
v[vl[j]].push_back(vl[j+1]);
}
}
memset(num,0,sizeof num);
}
}
//拓扑
for(i=0;i<=260000;i++){
if(is[i]&&!dis[i]) q.push(i);
}
while(!q.empty()){
int now=q.front();
ans.push_back(now);
q.pop();
for(i=0;i<v[now].size();i++){
if(--dis[v[now][i]]==0) {
q.push(v[now][i]);
}
}
}
if(ans.size()==n) {
for(i=0;i<ans.size();i++){
printf("%c",(ans[i]/10000)+'a');
}
}
else{
printf("-1\n");
}
}