題目鏈接:First! G
考慮某個單詞是否合法,我們從前往後掃。
對於在Trie上面,當前這個字母一定是最小的,所以我們可以利用這個關係判是否存在環。
還有,如果這個單詞存在某個前綴也是不合法的。
AC代碼:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=3e5+10;
int n,g[26][26],deg[26],ch[N][26],idx,cnt[N],vis[N],res; string str[N];
inline void insert(string &str){
int p=0;
for(int i=0;i<str.size();i++){
int k=str[i]-'a';
if(!ch[p][k]) ch[p][k]=++idx;
p=ch[p][k];
}
cnt[p]++;
}
inline int Top(){
queue<int> q; for(int i=0;i<26;i++) if(!deg[i]) q.push(i); int cnt=0;
while(q.size()){
int u=q.front(); q.pop(); cnt++;
for(int i=0;i<26;i++) if(g[u][i]){
if(--deg[i]==0) q.push(i);
}
}
return cnt==26;
}
inline int check(string &str){
int p=0; memset(g,0,sizeof g); memset(deg,0,sizeof deg);
for(int i=0;i<str.size();i++){
if(cnt[p]) return 0;
int k=str[i]-'a';
for(int j=0;j<26;j++) if(j!=k&&ch[p][j]&&!g[j][k]) deg[k]++,g[j][k]=1;
p=ch[p][k];
}
return Top();
}
signed main(){
ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
cin>>n;
for(int i=1;i<=n;i++) cin>>str[i],insert(str[i]);
for(int i=1;i<=n;i++) if(check(str[i])) vis[i]=1,res++;
cout<<res<<'\n';
for(int i=1;i<=n;i++) if(vis[i]) cout<<str[i]<<'\n';
return 0;
}