字典树
Time Limit: 1000MS
Memory Limit: 65536KB
Problem Description
遇到单词不认识怎么办? 查字典啊,已知字典中有n个单词,假设单词都是由小写字母组成。现有m个不认识的单词,询问这m个单词是否出现在字典中。
Input
含有多组测试用例。
第一行输入n,m (n>=0&&n<=100000&&m>=0&&m<=100000)分别是字典中存在的n个单词和要查询的m个单词.
紧跟着n行,代表字典中存在的单词。
然后m行,要查询的m个单词
n=0&&m=0 程序结束
数据保证所有的单词都是有小写字母组成,并且长度不超过10
Output
若存在则输出Yes,不存在输出No .
Example Input
3 2 aab aa ad ac ad 0 0
Example Output
No Yes
Hint
Author
gyx
静态分配内存,数组模拟
#include <stdio.h>
#include <string.h>
struct node
{
int isend; //是否结束
int next[26];
}L[5050000]; //静态分配内存
int top,n,m;
char a[20],b[20];
int creat() //创建新结点
{
memset(L[top].next,-1,sizeof(L[top].next));
L[top].isend = 0;
return top++;
}
int xiab(char c) // 求下标
{
return c - 'a';
}
void insert(int root,char *s) //插入
{
int i,len = strlen(s);
for(i = 0;i < len;i++)
{
if(L[root].next[xiab(s[i])] == -1)
{
L[root].next[xiab(s[i])] = creat();
}
root = L[root].next[xiab(s[i])];
}
L[root].isend = 1;
}
int search(int root,char *s)//查找
{
for(int i =0;s[i]!='\0';i++)
{
if(L[root].next[xiab(s[i])] == -1)
return 0;
root = L[root].next[xiab(s[i])];
}
return L[root].isend;
}
int main()
{
int i,j,root;
while(scanf("%d%d",&n,&m) != EOF&&(n||m))
{
top = 0;
root = creat();
for(i = 0;i < n;i++)
{
scanf("%s",a);
insert(root,a);
}
for(i = 0;i <m;i++)
{
scanf("%s",b);
printf("%s\n",search(root,b)?"Yes":"No");
}
}
return 0;
}
另一种做法,MLE不知为什么
静态分配内存,数组模拟
#include <stdio.h>
#include <string.h>
struct node
{
int isend; //是否结束
int next[26];
}L[5050000]; //静态分配内存
int top,n,m;
char a[20],b[20];
int creat() //创建新结点
{
memset(L[top].next,-1,sizeof(L[top].next));
L[top].isend = 0;
return top++;
}
int xiab(char c) // 求下标
{
return c - 'a';
}
void insert(int root,char *s) //插入
{
int i,len = strlen(s);
for(i = 0;i < len;i++)
{
if(L[root].next[xiab(s[i])] == -1)
{
L[root].next[xiab(s[i])] = creat();
}
root = L[root].next[xiab(s[i])];
}
L[root].isend = 1;
}
int search(int root,char *s)//查找
{
for(int i =0;s[i]!='\0';i++)
{
if(L[root].next[xiab(s[i])] == -1)
return 0;
root = L[root].next[xiab(s[i])];
}
return L[root].isend;
}
int main()
{
int i,j,root;
while(scanf("%d%d",&n,&m) != EOF&&(n||m))
{
top = 0;
root = creat();
for(i = 0;i < n;i++)
{
scanf("%s",a);
insert(root,a);
}
for(i = 0;i <m;i++)
{
scanf("%s",b);
printf("%s\n",search(root,b)?"Yes":"No");
}
}
return 0;
}
另一种做法,MLE不知为什么
#include <stdio.h>
#include <string.h>
char str[20];
struct node *L;
struct node
{
int isend; //0非最后一个节点,1最后一个节点
struct node *next[26]; //按字母编号
};
void insert(char str[]) //插入
{
int len = strlen(str);
if(len == 0)
return ;
int i;
struct node *q = L;
for(i = 0;i < len;i++)
{
int no = str[i] - 'a';
if(q->next[no] == NULL) //不存在该前缀
{
struct node *p;
p = (struct node *)malloc(sizeof(struct node));
chushihua(p);
q->next[no] = p;
q = p;
}
else //存在
{
q = q->next[no];
}
}
q->isend = 1; //最后一个节点,
}
void chushihua(struct node *p) //初始化
{
p->isend = 0;
for(int i = 0;i < 26;i++)
{
p->next[i] = NULL;
}
}
void find(char str[]) //查找
{
int len = strlen(str);
if(str == 0)
printf("No\n");
int i;
struct node *p = L;
for(i = 0;i < len;i++)
{
int no = str[i] - 'a';
if(p->next[no] != NULL)
{
p = p->next[no];
}
else
{
printf("No\n");
return ;
}
}
if(p->isend == 1)
printf("Yes\n");
else
printf("No\n");
}
void end(struct node *p)
{
int i;
for(i = 0;i < 26;i++)
{
if(p->next[i] != NULL)
end(p->next[i]);
}
free(p);
}
int main()
{
int n,m,i,j;
while(scanf("%d%d",&n,&m) != EOF&&(n||m))
{
L = (struct node *)malloc(sizeof(struct node));
chushihua(L);
for(i = 0;i < n;i++)
{
scanf("%s",str);
insert(str);
}
for(i = 0;i < m;i++)
{
scanf("%s",str);
find(str);
}
end(L);
}
return 0;
}
2071

被折叠的 条评论
为什么被折叠?



