CF - Fox And Names

原题: Problem - 510C - Codeforces

题意:给你n个字符串,这些字符串是按照某种字母规律排序的,判断是否存在这种规律,如果存在,要求找出字母排序的规律。

分析:拓扑排序,具体看代码注解。

题解:

#include <bits/stdc++.h>
using namespace std;

int n;
string s[105];
char ans[30];//存储答案
bool vis[30][30];//是否有连边
int in[30];//入度

void topsort()
{
    //找第i个答案
    for(int i=0;i<26;i++)
    {
        bool flag=0;//是否找到一个入度为0的点
        int tmp;//存储当前需要计入答案的字母
        for(int j=0;j<26;j++)
        {
            if(in[j]==0)
            {
                tmp=j;
                flag=1;
                break;
            }
        }
        //找不到说明存在环
        if(!flag)
        {
            cout<<"Impossible";
            return;
        }
        //找到后,存入答案,去掉这个点
        in[tmp]=-1;
        char now=(char)(tmp+'a');
        ans[i]=now;
        for(int j=0;j<26;j++)
        {
            if(vis[tmp][j]) in[j]--;
        }
    }

    cout<<ans;
}

int main()
{
    memset(in,0,sizeof in);
    memset(vis,0,sizeof vis);
    cin>>n;

    for(int i=1;i<=n;i++)
    {
        cin>>s[i];
    }

    //记录连边和入度
    bool flag1=1;//当后一个是前一个的前缀子串,必定不符合要求
    
    for(int i=1;i<n;i++)
    {
        int j=i+1;
        int len1=s[i].length();
        int len2=s[j].length();
        bool flag2=0;//判断是否有不同

        //逐位比较
        for(int k=0;k<min(len1,len2);k++)
        {
            if(s[i][k]!=s[j][k])
            {
                flag2=1;
                if(!vis[s[i][k]-'a'][s[j][k]-'a'])//没连过边
                {
                    vis[s[i][k]-'a'][s[j][k]-'a']=1;
                    in[s[j][k]-'a']++;//入度+1
                }
                break;//两个字符不同之后就不需要再判断了
            }
        }

        //后面的是前面的子串,不合法
        if(!flag2&&len1>len2)
        {
            flag1=0;
            break;
        }

    }

    if(!flag1)
    {
        cout<<"Impossible";
    }
  else topsort();

    return 0;
}
posted @ 2021-06-08 22:31  AtomsH  阅读(48)  评论(0)    收藏  举报