Технокубок 2018 - Отборочный Раунд 1 D. Polycarp's phone book(枚举+字典树)

题目链接
Технокубок 2018 - Отборочный Раунд 1 D. Polycarp's phone book(枚举+字典树)_第1张图片
Технокубок 2018 - Отборочный Раунд 1 D. Polycarp's phone book(枚举+字典树)_第2张图片
思路:因为每个字符串长度都是9,那么我们就暴力去每个字符串每个长度的字串建字典树,然后查询的时候先将第i个字符串的所有长度的字串全部删掉,再查一下字典树中不存在的那个字串就行了,由于长度要最小我们可以按长度从小到大枚举就可以了,最后别忘了恢复原状。

#include
using namespace std;
typedef long long ll;
const int maxn=2e5+1;
int n,cnt=0,tree[maxn*4][10],sum[maxn*4];
string s[maxn];
void insert(string x)
{
	int u=0;
	for(int i=0;i<x.size();++i)
	{
		int t=x[i]-'0';
		if(!tree[u][t]) tree[u][t]=++cnt;
		u=tree[u][t];
	}
	sum[u]++;
}
void del(string x)
{
	int u=0;
	for(int i=0;i<x.size();++i)
	u=tree[u][x[i]-'0'];
	sum[u]--;
}
bool check(string x)
{
	int u=0;
	for(int i=0;i<x.size();++i)
	u=tree[u][x[i]-'0'];
	return !sum[u];
}
string query(string x)
{
	for(int len=1;len<=9;++len)
		for(int i=0;i+len<=x.size();++i)
	del(x.substr(i,len));
		for(int len=1;len<=9;++len)
		for(int i=0;i+len<=x.size();++i)
	{
		if(check(x.substr(i,len))) {
			string ans=x.substr(i,len);
				for(int len=1;len<=9;++len)
		for(int i=0;i+len<=x.size();++i)
			insert(x.substr(i,len));
			return ans;
		}
	}
}
int main()
{
	scanf("%d",&n);
	for(int k=1;k<=n;++k) 
	{
		cin>>s[k];
		for(int len=1;len<=9;++len)
		for(int i=0;i+len<=s[k].size();++i)
		insert(s[k].substr(i,len));
	}
	for(int i=1;i<=n;++i)
	cout<<query(s[i])<<endl; 
}

你可能感兴趣的:(字典树)