zoukankan      html  css  js  c++  java
  • 牛客比赛-假的字符串-Trie+拓扑

    链接:https://www.nowcoder.com/acm/contest/59/B
    来源:牛客网

    题目描述

    给定n个字符串,互不相等,你可以任意指定字符之间的大小关系(即重定义字典序),求有多少个串可能成为字典序最小的串,并输出它们

    输入描述:

    第一行一个数表示n
    之后n行每行一个字符串表示给定的字符串

    输出描述:

    第一行输出一个数x表示可行的字符串个数
    之后输出x行,每行输出一个可行的字符串
    输出的顺序和输入的顺序一致
    示例1

    输入

    6
    mcfx
    ak
    ioi
    wen
    l
    a

    输出

    5
    mcfx
    ioi
    wen
    l
    a

    备注:

    对于100%的数据,
    n <= 30000 , 字符串总长<= 300000
    字符集为小写字符
    题目很是扯淡,,数据更扯淡,,不知道字符最大长度,MLE了几次,改小了又WA,还好最后试对了= =要是给出字符串最大长度就好了。
    比赛时根本不知道题目在说什么鬼,其实就是询问某个字符串是否能最小,考虑作为最小的条件,S(最小)与另个字符串P比较时,遇到的第一个不相等的字符(位置j)时,S[j]<P[j]要成立,
    我们将所有的字符串建成一颗trie时,对于某个被当做最小的字母,经过的所有的节点都要小于它的兄弟节点。暴力的找一下每个节点的兄弟建图即可。e[i][j]=1表示字符i<j成立。
    我们只要找到所有的这些条件,在讨论是否能同时满足即可,这个问题显然就是拓扑排序,只要不出现环即可,问题转化为找图中是否有环。用floyd传递闭包即可。这个题有点卡时空。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int MAX_SIG=26;
     4 const int MAX_NOD=250000;
     5 char str[30005][25];
     6 bool ok[30005];
     7 int ch[MAX_NOD][MAX_SIG];
     8 int val[MAX_NOD],sz;
     9 char s[MAX_NOD];
    10 int e[30][30];
    11 int idx(char c){return c-'a';}
    12 
    13 void _insert(char *s)
    14 {
    15     int u=0,n=strlen(s);
    16     for(int i=0;i<n;++i){
    17         int c=idx(s[i]);
    18         if(!ch[u][c]) ch[u][c]=sz++;
    19         u=ch[u][c];
    20     }
    21     val[u]++;
    22 }
    23 
    24 bool solve(int k)
    25 {
    26   memset(e,0,sizeof(e));
    27   int n=strlen(str[k]);
    28   int u=0;
    29   for(int i=0;i<n;++i){
    30     int c=idx(str[k][i]);
    31     if(val[ch[u][c]]&&i!=n-1) return 0;
    32     for(int j=0;j<MAX_SIG;++j){
    33         if(j==c) continue;
    34         if(ch[u][j]) e[c][j]=1;
    35     }
    36     u=ch[u][c];
    37   }
    38   for(int k=0;k<MAX_SIG;++k)
    39   {
    40       for(int i=0;i<MAX_SIG;++i)
    41       {
    42           if(!e[i][k]) continue;
    43           for(int j=0;j<MAX_SIG;++j)
    44           {
    45             if(e[k][j]&&e[j][i]) return 0;
    46           }
    47       }
    48       for(int i=0;i<MAX_SIG;++i)
    49       {
    50           if(!e[i][k]) continue;
    51           for(int j=0;j<MAX_SIG;++j)
    52           {
    53               if(e[k][j]) e[i][j]=1;
    54           }
    55       }
    56   }
    57     return 1;
    58 }
    59 
    60 int main()
    61 {
    62     int n;
    63     while(cin>>n){
    64         sz=1;
    65         for(int i=1;i<=n;++i){
    66             scanf("%s",str[i]);
    67             _insert(str[i]);
    68         }
    69         int ans=0;
    70         for(int i=1;i<=n;++i){
    71             int k=solve(i);
    72             if(k){
    73                 ok[i]=1;
    74                 ans++;
    75             }
    76         }
    77         cout<<ans<<endl;
    78         for(int i=1;i<=n;++i)
    79             if(ok[i]) cout<<str[i]<<endl;
    80     }
    81     return 0;
    82 }
  • 相关阅读:
    python xlwt 设置单元格样式-合并单元格
    Ubuntu 16.04配置国内高速apt-get更新源
    python3.5 安装python3-tk
    m4a 转 wav
    hmm前后向算法
    hmm三个问题
    veterbi
    马尔科夫和隐马尔科夫
    Exception in thread "main" java.lang.UnsupportedClassVersionError: org/apache/ma ven/cli/Maven/java与javac版本不一致问题
    spring 配置定时任务
  • 原文地址:https://www.cnblogs.com/zzqc/p/8401024.html
Copyright © 2011-2022 走看看