http://codeforces.com/contest/861/problem/D
给定n个9位长的数字。
问你最短的他的子串,并且这个子串没有在其他字符串中出现过。
方法:字典树把 所有字符串的所有后缀加进去,然后统计的时候,把当前要 做的 字符串的所有 后缀删掉,然后再再当前这个树上 查询没有出现的 最短的 这些后缀的 前缀。
(所有子串都可以表示为 母串某一个后缀的前缀。)
#include <bits/stdc++.h>
/* 策略(我也没见过这种霸气的操作啊)
维护每一个字符串的所有后缀,
然后查找的时候,再把他的后缀删除了,
网上找了一套 题解,当模板。。
query和 主函数是我自己写的。
*/
using namespace std;
int mx;
char a[70010][10],temp[10],ans[10];
int len2;
struct trie
{
trie *next[10];
int cnt;
trie()
{
memset(next,0,sizeof(next));
cnt=0;
}
};
trie *root;
void insert(char *s)
{
trie *p=root;
int i,k;
for(i=0;s[i]!='\0';++i)
{
k=s[i]-'0';
if(p->next[k]==NULL)
p->next[k]=new trie();
p=p->next[k];
p->cnt++;
}
}
void Delete(char *s)
{
trie *p = root;
int i,k;
for(i=0;s[i]!='\0';i++)
{
k = s[i]-'0';
p = p->next[k];
p->cnt--;
}
}
void del(trie *p)
{
for(int i=0;i<10;i++)
if(p->next[i]!=NULL)
del(p->next[i]);
free(p);
}
void query(char *s){
//memset(temp,0,sizeof(temp));
trie *x=root;
int len1=0;
for(int i=0;s[i]!='\0';i++){
temp[len1++]=s[i];
x=x->next[s[i]-'0'];
if(x->cnt==0){
if(len1<=len2){
temp[len1]='\0';
strcpy(ans,temp);
len2=len1;
break;
}
}
}
}
int main()
{ int m;
scanf("%d",&m);
//getchar();
root=new trie();
for(int i=0;i<m;i++){
scanf(" %s",a[i]);
for(int j=0;j<9;j++){
insert(a[i]+j);
}
}
len2=1e7;
for(int i=0;i<m;i++){
len2=1e7;
for(int j=0;j<9;j++)
Delete(a[i]+j);
for(int j=0;j<9;j++)
query(a[i]+j);
for(int j=0;j<9;j++)
insert(a[i]+j);
//cout<<len2<<endl;
printf("%s\n",ans);
}
// cout<<len2<<endl;
return 0;
}