题意:给你一堆电话号码,让你判断其中是否有号码是其他号码的前缀。
思路:用电话号码建一颗字典树,插入一个单词的时候直接判断。插入完一个单词之后把它位置u的v【u】置为1,如果这个单词是其他单词的前缀,那么插入完这个单词之后它的下一个位置一定有节点。如果该单词包含其他单词的前缀,则一定经过v[u]>0的节点。具体见代码。需要注意有就输出NO,没有输出YES。。。(我说怎么刚开始的代码和样例结果相反呢)
AC代码:
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int mx=100010;
struct node{
int ch[mx][10];
int sz;
int v[mx];
void init(){
memset(ch[0],0,sizeof(ch[0]));sz=1;
v[0]=0;
}
bool add(char *s)
{
bool f=1;
int u=0,n=strlen(s);
for(int i=0;i<n;i++)
{
int id=s[i]-'0';
if(ch[u][id]==0)
{
ch[u][id]=sz;
v[sz]=0;
memset(ch[sz],0,sizeof(ch[sz]));
sz++;
}
u=ch[u][id];
if(v[u]>0) f=0;//该单词包含其他单词的前缀,则一定经过v[u]>0的节点
}
v[u]=1;
if(f)
{
for(int i=0;i<=9;i++)//该单词是其他单词的前缀,则一定可以沿这条路继续往下走
if(ch[u][i]!=0) {f=0;break;}
}
return !f;
}
}a;
int main()
{
int T,m,k;
char b[mx];
while(scanf("%d",&T)!=EOF)
{
while(T--)
{
a.init();//初始化写在哪一定要注意
scanf("%d",&m);
bool jud=0;
for(int j=0;j<m;j++)
{
scanf("%s",b);
if(jud) continue;
jud=a.add(b);
}
if(jud) printf("NO\n");
else printf("YES\n");
}
}
return 0;
}