• hoj12614 Dictionary ——拓扑排序找环&&比赛残留题


    题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=12614&courseid=247

    题目大意:

      有一种字典。把字典中的符号映射到英文字母。输入一个n,然后是n行映射后的单词,判断这n个单词是不是符合字典序,所谓字典序就是前面的单词可以是后面的单词的前缀,并且这n个单词符合字符串排序后的顺序,这是针对原来的字母的,而不是映射之后的字母。

    题目思路:

      需要考虑映射之后的字母的相对顺序,来考虑是不是在原来的字母表中是不是符合字典序。

      这道题目开始没看懂,最关键的第一段描述没有注意到,结果样例都看不懂。纠结了好久。但是涉及到前缀,觉得应该是字典树。

      后来终于注意到第一段了,终于理解题目意思了。悲剧的是,还是纠结在字典树上面,老是在这方面想。没有思路。知道考虑相对顺序,但是不知道怎么映射……过程中llh其实提到了一下两个字母的相对顺序可以用边表示,可是,我没有继续往下想!后来听人家说,可以建图,然后找环。唉,原来就是llh那样想的。

      回来之后,认真想了一下。方法是:预处理的过程中判断是不是出现这种情况:后面的单词是前面的单词的前缀,这是不符合条件的。同时在预处理的过程中建图,用临界表,如果一个字母A在另一个字母B的后面,就把B插入到A的出边表里面。然后就是在这个图里面找环,如果出现环了,就是不符合条件的。找环的方法就是刚刚做过的拓扑排序的方法。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cctype>
     6 #include <stack>
     7 #include <queue>
     8 #include <map>
     9 #include <set>
    10 #include <vector>
    11 #include <cmath>
    12 #include <algorithm>
    13 #define lson l, m, rt<<1
    14 #define rson m+1, r, rt<<1|1
    15 using namespace std;
    16 typedef long long int LL;
    17 const int MAXN =  0x3f3f3f3f;
    18 const int  MIN =  -0x3f3f3f3f;
    19 const double eps = 1e-9;
    20 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1},
    21   {1,1},{1,-1},{-1,-1}};
    22 int n; char a[509][17];
    23 struct ArcNode {
    24   int to; struct ArcNode *next;
    25 };
    26 ArcNode *List[50];
    27 int Count[50];
    28 bool topsort()
    29 {
    30   int i = 0, j, k, top = -1;
    31   ArcNode *temp; bool flag = false;
    32   for (i = 0; i < 26; ++i) {
    33     if (Count[i] == 0) { Count[i] = top; top = i; }
    34   }
    35   for (i = 0; i < 26; ++i) {
    36     if (top == -1) { flag = true; break; }
    37     j = top; top = Count[top]; temp = List[j];
    38     while (temp) {
    39       k = temp->to; Count[k]--;
    40       if (Count[k] == 0) { Count[k] = top; top = k; }
    41       temp = temp->next;
    42     }
    43   }
    44   if (flag) return false;
    45   else return true;
    46 }
    47 int main(void){
    48 #ifndef ONLINE_JUDGE
    49   freopen("hnu247.in", "r", stdin);
    50 #endif
    51   while (~scanf("%d", &n)) {
    52     if (!n) break;
    53     int i, j, u, v; bool flag = true; ArcNode *temp;
    54     for (i = 0; i < n; ++i) {
    55       scanf("%s", a[i]);
    56     }
    57     memset(List, 0, sizeof(List));
    58     for (i = 0; i < 27; ++i) Count[i] = 0;
    59     for (i = 1; i < n; ++i) {
    60       for (j = 0; j < strlen(a[i-1]); ++j) {
    61         if (j >= strlen(a[i])) { flag = false; break; }
    62         if (a[i-1][j] != a[i][j]) {
    63           u = a[i-1][j] - 'a'; v = a[i][j] - 'a';
    64           Count[v]++; temp = new ArcNode;
    65           temp->to = v; temp->next = NULL;
    66           temp->next = List[u]; List[u] = temp;
    67           break;
    68         }
    69       }
    70       if (!flag) break;
    71     }
    72     if (!flag) { printf("no\n"); continue; }
    73     if (topsort()) { printf("yes\n"); }
    74     else printf("no\n");
    75   }
    76 
    77   return 0;
    78 }

      做题的时候还是有个误区:第一感觉这道题目应该用到什么数据结构或算法,就硬往里面套,结果,很限制思路。其实应该是,先认真分析这道题目,是解决什么问题的,应该怎么解决,然后在思考可能什么样的数据结构或者算法能起作用。而不是硬生生的套数据结构,一条路走到黑……

      很多人过这道题目,分析完之后,其实这应该也是很基础的一道题目。也许是自己做的太少了,当时想法都没有……

  • 相关阅读:
    leetcode 11. 盛最多水的容器
    gluoncv 导入方式
    python import
    leetcode 55.跳跃游戏
    leetcode 31. 下一个排列
    gluoncv 下载预训练模型速度太慢
    gluoncv voc_detection
    shuf 按行打乱文本命令
    __call__
    @property 装饰器
  • 原文地址:https://www.cnblogs.com/liuxueyang/p/3050902.html
Copyright © 2020-2023  润新知