题目链接:HDU 1671 Phone List
题意:判断所给的字符串中是否存在一个字符串是其他任意字符串的前缀。
刚学字典树。
注意初始化,
AC代码:
#include<stdio.h>
#include<string.h>
#define Word_Len 100002
#define Sigma_size 30
struct Trie
{
int ch[Word_Len][Sigma_size]; //Word_Len是字典树的节点数 若都是小写字母Sigma_size=26
int Have_word[Word_Len]; //这个节点下有几个单词
int value[Word_Len]; // 这个节点附带的信息,初始化为0表示这个节点不存在单词,所以节点带的信息必须!=0
int sz; //当前节点数
void init() //初始化字典树
{
sz=1;
memset(ch[sz],0,sizeof ch[sz]);
memset(Have_word,0,sizeof Have_word);
memset(value,0,sizeof value);
}
int idx(char c) //字符串编号
{
return c-'0';
}
void build(char s[])
{
int i;
int u=0;
int len=strlen(s);
for(i=0;i<len;i++)
{
int c=idx(s[i]);
if(!ch[u][c]) //节点不存在就新建后附加
{
memset(ch[sz],0,sizeof ch[sz]);
value[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c]; //u等于下前一个字母的节点
value[u]=c;
Have_word[u]++; //现在的u就是这个单词的最后一个位置
}
}
int find_word(char s[])
{
int i;
int u=0;
int len=strlen(s);
for(i=0;i<len;i++)
{
int c=idx(s[i]);
if(!ch[u][c]) //节点不存在
return 0;
u=ch[u][c];
}
return Have_word[u];
}
};
Trie ac;
char num[50010][20];
int main()
{
int t;
int i,n;
while(scanf("%d",&t)!=EOF)
{
while(t--)
{
ac.init();
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%s",num[i]);
ac.build(num[i]);
}
for(i=0;i<n;i++)
{
int ans=ac.find_word(num[i]);
// printf("(%d)\n",ans);
if(ans>1)
break;
}
if(i<n)
printf("NO\n");
else
printf("YES\n");
for(i=0;i<n;i++)
memset(ac.ch[i],0,sizeof ac.ch[i]);//初始化,刚开始没考虑到
}
}
return 0;
}
/*
10
2
111
112
2
111
1112
*/
反思:程序的初始化很关键,没做好初始化,跑多个案例,答案天差地别。学习一些算法刚开始可以采用黑箱方法,前提是原理要明白。