wannafly 练习赛11 B 假的字符串(字典树+建边找环)
链接:https://www.nowcoder.com/acm/contest/59/B
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
64bit IO Format: %lld
题目描述
给定n个字符串,互不相等,你可以任意指定字符之间的大小关系(即重定义字典序),求有多少个串可能成为字典序最小的串,并输出它们
输入描述:
第一行一个数表示n
之后n行每行一个字符串表示给定的字符串
输出描述:
第一行输出一个数x表示可行的字符串个数
之后输出x行,每行输出一个可行的字符串
输出的顺序和输入的顺序一致
示例1
输入
6 mcfx ak ioi wen l a
输出
5 mcfx ioi wen l a
备注:
对于100%的数据,
n <= 30000 , 字符串总长<= 300000
字符集为小写字符
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
1 #include <bits/stdc++.h> 2 #define mst(a,b) memset((a),(b), sizeof a) 3 #define lowbit(a) ((a)&(-a)) 4 #define IOS ios::sync_with_stdio(0);cin.tie(0); 5 using namespace std; 6 typedef long long ll; 7 const int mod=1e9+7; 8 const int maxn=3e5+100; 9 string use[30010]; 10 int head,cnt; 11 int nx[maxn][28]; 12 int cc[maxn]; 13 bool co[maxn]; 14 void init(int k){ 15 int now=head; 16 int sz=use[k].size(); 17 for(int i=0;i<sz;++i){ 18 int d=use[k][i]-'a'; 19 if(!nx[now][d])nx[now][d]=++cnt; 20 now=nx[now][d]; 21 } 22 ++cc[now]; 23 } 24 bool mp[26][26]; 25 int vis[26]; 26 bool dfs(int pos){ 27 vis[pos]=-1; 28 for(int i=0;i<26;++i)if(i!=pos&&mp[pos][i]){ 29 if(!vis[i]){ 30 if(!dfs(i))return false; 31 }else{ 32 if(vis[i]==-1)return false; 33 } 34 } 35 vis[pos]=1; 36 return true; 37 } 38 bool ok(int k){ 39 int now=head; 40 int sz=use[k].size(); 41 mst(mp,0);mst(vis,0); 42 for(int i=0;i<sz;++i){ 43 int d=use[k][i]-'a'; 44 for(int j=0;j<26;++j)if(j!=d&&nx[now][j]){ 45 mp[j][d]=1; 46 } 47 now=nx[now][d]; 48 if(i!=sz-1&&cc[now])return false; 49 } 50 for(int i=0;i<26;++i)if(!vis[i]&&!dfs(i))return false; 51 return true; 52 } 53 int main(){ 54 #ifdef local 55 freopen("in.txt","r",stdin); 56 //freopen("out.txt","w",stdout); 57 #endif 58 IOS 59 int n;cin>>n; 60 for(int i=1;i<=n;++i){ 61 cin>>use[i]; 62 init(i); 63 } 64 int ans=0; 65 for(int i=1;i<=n;++i)if(ok(i)){ 66 co[i]=true; 67 ++ans; 68 } 69 cout<<ans<<endl; 70 for(int i=1;i<=n;++i)if(co[i])cout<<use[i]<<endl; 71 return 0; 72 }