2022春每日一题:Day 32

题目:[USACO12DEC]First! G

不太记得当时怎么想的了,但是显然,当一个字符串的前缀存在则他一定不是first,然后做法:对于每个字符串,把每个字符结尾跟他有相同前缀的单词的同元素建边,保证这个元素严格大于其他元素,然后判环,有环的话说明不能是first,反之则是。

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <iostream>
const int N=3e4+5,M=3e5+5;
using namespace std;
int n,m,tot,num,ss[N],vis[N],rd[26];
string s,dic[N];
vector <int> g[26];
namespace trietree
{
	struct trie
	{
		int son[26],tag;
	}e[M];
	void insert(int len)
	{
		int p=0;
		for(int i=0;i<len;i++)
		{
			int k=s[i]-'a';
			if(!e[p].son[k])
			    e[p].son[k]=++tot;
			p=e[p].son[k];
		}
		e[p].tag=1;
	}
	bool topusort()
	{
		queue <int> q;
		while(!q.empty())
		    q.pop();
		int cnt=0;
		for(int i=0;i<26;i++)
		    if(!rd[i])
		        q.push(i);
		while(!q.empty())
		{
			int now=q.front();
			int len=g[now].size();
			++cnt;
			q.pop();
			for(int i=0;i<len;i++)
			{
				int k=g[now][i];
				--rd[k];
				if(!rd[k])
				    q.push(k);
			}
		}
		return cnt==26;
	}
	void clear(int len,int id)
	{
		int p=0,ok=0;
		s=dic[id];
		for(int i=0;i<26;i++)
		    g[i].clear(),rd[i]=0;
		for(int i=0;i<len;i++)
		{
			if(e[p].tag)
			    ok=1;
			int k=s[i]-'a';
			for(int j=0;j<26;j++)
			    if(j!=k && e[p].son[j])
			        g[k].push_back(j),rd[j]++;
			p=e[p].son[k];
		}
		if(!topusort())
		    ok=1;
		if(ok)
		    vis[id]=1;
		num+=ok;
	}
}
using namespace trietree;
int main()
{
	ios::sync_with_stdio(0);
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		ss[i]=s.length();
		dic[i]=s;
		insert(ss[i]);
	}
	for(int i=1;i<=n;i++)
	    clear(ss[i],i);
	cout<<n-num<<'\n';
	for(int i=1;i<=n;i++)
	    if(!vis[i])
	        cout<<dic[i]<<'\n';
	return 0;
}
posted @   __honey  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示