HDU 1671 Phone List(字典树Trie)
http://acm.hdu.edu.cn/showproblem.php?pid=1671
题意:
给你多个由0-9构成的字符串集合,问你这个集合中是否有一个字符串是其他字符串的前缀?
分析:
直接构造字典树,然后一一插入每个字符串,判断是否有比当前字符串短或长的同一路径的字符串已经在树中了.
注意:字典树中如果该节点是一个电话号码的尾节点,那么val值为1,否则为0.
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxnode=100000+1000;
const int sigma_size=10;
struct Trie
{
int ch[maxnode][sigma_size];
int val[maxnode];//非单词节点为0,单词节点为1
int sz;
void init()
{
sz=1;
val[0]=0;
memset(ch[0],0,sizeof(ch[0]));
}
bool insert(char *s)
{
bool ok=true;
int n=strlen(s),u=0;
for(int i=0;i<n;i++)
{
int id=s[i]-'0';
if(ch[u][id]==0)
{
ch[u][id]=sz;
val[sz]=0;
memset(ch[sz],0,sizeof(ch[sz]));
sz++;
}
u=ch[u][id];
if(val[u]>0)//存在当前插入串s的前缀
ok=false;
}
val[u]=1;
if(ok)
{
for(int i=0;i<sigma_size;i++)
if(ch[u][i]!=0)//存在包含当前插入串的长串
{
ok=false;
break;
}
}
return ok;
}
};
Trie trie;
char word[20];
int main()
{
int kase;
scanf("%d",&kase);
while(kase--)
{
int n;
scanf("%d",&n);
trie.init();
bool ok=true;
for(int i=0;i<n;i++)
{
scanf("%s",word);
if(ok)
ok=trie.insert(word);
}
if(ok)printf("YES\n");
else printf("NO\n");
}
return 0;
}