没有见到过字典树的时候,以为会很神秘。
其实,如果链表学的差不多了,实现字典树那就是手到擒来。
做了几道题,效果还好。。
第一道:
NYOJ 290 动物统计加强版 点击打开链接
典型的字典树。裸的字典树。还是比较好的。不是太坑。算是练手了吧。直接就写了,也不用放内存什么的。但是,最好的还是把内存给放了吧,要不太占内存。
直接代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=26;
struct Node{
int count;
Node *next[N];
}*root;
int MaxConut=-1;
char ans[N];
Node* Build(){//建立以个节点,每个节点都最多有26个子节点,虽然真真的子节点数不确定.
Node* p=(Node*)malloc(sizeof(Node));
for(int i=0;i<N;i++){
p->next[i]=NULL;
}
p->count=0;
return p;
}
void Save(char *s){//保存word
int len=strlen(s);
if(len==0) return ;
Node* p=root;
for(int i=0;i<len;i++){
if(p->next[s[i]-'a']==NULL)
p->next[s[i]-'a']=Build();//不存在的话建立该节点.
p=p->next[s[i]-'a'];
}
p->count++;
if(p->count>=MaxConut) {
MaxConut=p->count;
strcpy(ans,s);
}
}
int main(){
// freopen("Input.txt","r",stdin);
int n;
scanf("%d",&n);
root=Build();
char animal[N];
for(int i=1;i<=n;i++){
scanf("%s",animal);
Save(animal);
}
printf("%s %d\n",ans,MaxConut);
return 0;
}
可以看到,其实,字典树,写起来也就50行的事情。不难。
第二道:
Phone List Hdu 1671 点击打开链接 Poj 3630 点击打开链接 NYOJ 163 点击打开链接
这题就比较坑点了。同样的代码,在Hdu,ML。在Poj TL。在NYOJ上WA。
只能说,数据不同,结果也会有所不同。由此可见,数据的重要性。
这题,也是比较裸的字典树吧。
有两中情况,一,先存了比较短的(也就是前缀)。二,先存了比较长的。这两中各判断一下就可以。
说明一下为什么会出现不同的结果。
Hdu,ML。就是因为自己没有释放内存,导致,无用内存积累,开辟新的内存又过多,导致ML。
Poj,TL。就是因为在动态分配内存的时候,过多的调用各种函数,导致超时。这时候就需要静态的来开辟空间了。
NYOJ,WA。这个是因为,自己在判断两种的时候,有一点小小的错误。
动态:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=10;
struct Node{
bool m;
Node *next[N];
};
Node* Build(){
Node *p=(Node*)malloc(sizeof(Node));
for(int i=0;i<N;i++){
p->next[i]=NULL;
}
p->m=false;
return p;
}
bool Save(char *s,Node *root){
int i,len=strlen(s);
// if(len==0) return false;
Node *p=root;
bool snack=false;
for(i=0;i<len;i++){
if(p->next[s[i]-'0']==NULL){
p->next[s[i]-'0']=Build();
snack=true;//没有开辟过新的空间.
}
else {
if(p->next[s[i]-'0']->m)
return true;
}
p=p->next[s[i]-'0'];
}
if(!snack) return true;
p->m=true;
return false;
}
void del(Node* p){
for(int i=0;i<N;i++){
if(p->next[i]!=NULL)
del(p->next[i]);
delete(p->next[i]);
}
}
int main(){
// freopen("1.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--){
int n;
char number[N];
scanf("%d",&n);
Node *root=Build();
bool flag=false;
for(int i=1;i<=n;i++){
scanf("%s",number);
if(!flag)
flag=Save(number,root);
}
if(flag) printf("NO\n");
else printf("YES\n");
del(root);
}
return 0;
}
静态:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=10;
const int M=1000003;
struct Node{
bool flag;
Node *next[N];
}node[M];
int top;
Node* Build(){
Node *p=&node[top++];
for(int i=0;i<N;i++){
p->next[i]=NULL;
}
p->flag=false;
return p;
}
bool Save(char *s,Node* root){
int len=strlen(s);
if(len==0) return false;
Node *p=root;
bool mark=false;
for(int i=0;i<len;i++){
if(p->next[s[i]-'0']==NULL){
mark=true;
p->next[s[i]-'0']=Build();
}
else if(p->next[s[i]-'0']->flag){
return true;
}
p=p->next[s[i]-'0'];
}
if(!mark) return true;
p->flag=true;
return false;
}
int main(){
// freopen("1.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
char number[N];
bool ans=false;top=0;
Node *root=Build();
for(int i=1;i<=n;i++){
scanf("%s",number);
if(!ans) ans=Save(number,root);
}
if(ans) printf("NO\n");
else printf("YES\n");
}
return 0;
}
很给力的题目。
第三道:
NYOJ 685 查找字符串 点击打开链接
还是裸的字典树。
直接代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=17;
const int M=29;
struct Node{
int count;
Node* next[M];
}*root;
Node* Build(){
Node* p=(Node*)malloc(sizeof(Node));
for(int i=0;i<M;i++){
p->next[i]=NULL;
}
p->count=0;
return p;
}
int find(char x){
if(x>='a'&&x<='z') return x-'a';
else if(x=='@') return 27;
else if(x=='+') return 28;
else return -1;
}
void Save(char *s){
int len=strlen(s);
if(len==0) return ;
Node *p=root;
for(int i=0;i<len;i++){
int k=find(s[i]);
if(p->next[k]==NULL){
p->next[k]=Build();
}
p=p->next[k];
}
p->count++;
}
int search(char *s){
int len=strlen(s);
Node* p=root;
for(int i=0;i<len;i++){
int k=find(s[i]);
if(p->next[k]==NULL)
return 0;
p=p->next[k];
}
return p->count;
}
void del(Node *p){
for(int i=0;i<M;i++){
if(p->next[i]!=NULL)
del(p->next[i]);
delete(p->next[i]);
}
}
int main(){
// freopen("Input.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--){
int n,m;
scanf("%d%d",&n,&m);
char word[N];
root=Build();
for(int i=1;i<=n;i++){
scanf("%s",word);
Save(word);
}
for(int i=1;i<=m;i++){
scanf("%s",word);
if(strlen(word)>15) printf("0\n");
else printf("%d\n",search(word));
}
del(root);
}
return 0;
}
比较简单。
今天的字典树就先告一段落了。