1 条题解

  • 0
    @ 2025-10-8 16:53:57
    #include <bits/stdc++.h>
    using namespace std;
    char s[51100][110];//s[1]-s[n]为小红修改后的单词 ,s[0]为需要小红给出的密语 
    int Map[150][150], rd[150], ys[150];bool v[150];
    //Map[c1][c2]表示原字典序中错误字母c1在错误字母c2前。
    //rd[c]表示错误字母c有多少入度(多少个错误字母在c前) 
    //ys[c]表示错误字母c对应的原字母
    //v[c]表示错误字母c有出现过 
    int main()
    {
        int n, m;scanf("%d%d", &n, &m);if(m <= 1){printf("0\n");return 0;}//如果单词只有1个,那无法破解 
    	memset(v, 0, sizeof(v));
        for(int i=1; i<=m; i++)//输入m个小红修改过的单词 
        {
            scanf("%s", s[i]);for(int j=0; j<strlen(s[i]); j++)v[s[i][j]]=1;//标记这些错误单词的每个字母出现过 
        }
        scanf("%s", s[0]);//输入小红给出的密语 
        for(int i=0; i<strlen(s[0]); i++)if(!v[s[0][i]]){printf("0\n");return 0;}//如果密语的字母没有出现过也没法破解 
        //下来建立拓扑关系 
        memset(rd, 0, sizeof(rd));
        memset(Map, 0, sizeof(Map));
        for(int i=2; i<=m; i++)//每个错误单词都和前一个单词进行对照,看看是那个字母影响了它们原来的字典序,从而判断这两个错误字母原来的前后顺序 
        {
            int l1 = strlen(s[i-1]), l2 = strlen(s[i]);
            for(int j=0; j<min(l1, l2); j++)
            {
                if(s[i-1][j] != s[i][j]){Map[s[i-1][j]][s[i][j]] = 1;rd[s[i][j]]++;break;}
            }
        }
    
        for(int i=1; i<=n; i++)//每次找出一个(而且只能刚好一个)入度为0的字母,它就是原来的第i个字母 
        {
            int t = 0;//当前这一次只能找到一个入度为0的字母,如果找到多于1个,则无法破解 
            char c1;
            for(char c='a'; c < 'a' + n; c++)
            {
                if(rd[c] == 0)
                {
                	t++;if(t > 1){printf("0\n");return 0;}
    				rd[c] = -1;
                    ys[c] = 'a' + i - 1;
    				c1 = c;
                }
            }
    		if(t == 0){printf("0\n");return 0;}//找不到入度为0的字母,也无法破解 
    		for(char c2='a'; c2 < 'a' + n; c2++)if(Map[c1][c2] == 1)rd[c2]--;
        }
        for(int i=0; i<strlen(s[0]); i++)printf("%c", ys[s[0][i]]);
        printf("\n");
        return 0;
    }
    
    • 1

    *【拓扑(难度:4)】破解密语

    信息

    ID
    770
    时间
    1000ms
    内存
    128MiB
    难度
    3
    标签
    递交数
    34
    已通过
    20
    上传者