First! G

題目鏈接: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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章