您的位置:首页 > 其它

POJ3630 Phone List+字典数三种申请内存的方法--动态、静态、半动态

2014-08-06 10:49 295 查看
POJ3630Phone
List
+字典数三种动态和静态申请内存的方法

Description:

Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let's say the phone catalogue listed these numbers:

Emergency 911
Alice 97 625 999
Bob 91 12 54 26

In this case, it's not possible to call Bob, because the central would direct your call to the emergency line as soon as you had dialled the first three digits of Bob's phone number. So this list would not be consistent.

[b]Input

[/b]

[b]The first line
of input gives a single integer, 1 ≤ t ≤
40, the number of test cases. Each test case starts with n,
the number of phone numbers, on a separate line, 1 ≤ n ≤
10000. Then follows n lines
with one unique phone number on each line. A phone number is a sequence of at most ten digits.

[/b]

[b]Output

[/b]

For
each test case, output "YES" if the list is consistent, or "NO" otherwise.



[b]Sample
Input


[/b]


2
3
911
97625999
91125426
5
113
12340
123440
12345
98346

Sample Output


NO
YES


题意很简单:就是给你一系列的字符串,容易过其中有一个字符串是其中一个字符串的前缀,就输出NO,否则输出YES。

解题思路也不难,只要在建树把字符串一个个放进去,然后边放边判断。这里要注意的是判断的时候分类讨论:1、现在判断的字符串是之前放进去的字符串的前缀 2、之前放进去的字符串是现在判断的字符串的前缀。

这里然后介绍三种申请内存的方法

1、动态申请内存,这个是三种里面速度最慢的,因为要逐个的去申请结构体的内存。(针对这道题目,在杭电的HDU1671能过,但在POJ上却过不了,这个让我当初在POJ上TLE了无数次)

<pre name="code" class="html">#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 10
char s[30];
bool flag;
typedef struct tree{
tree *next[MAX];
bool v;
};
tree *root;
void creattree(char *str)
{
tree *p=root,*q;
int n=strlen(str);
for(int i=0;i<n;i++)
{
int id=str[i]-'0';
if(p->next[id]==NULL)
{
q=(tree *)malloc(sizeof(tree));    ///动态申请内存
q->v=0;
for(int j=0;j<MAX;j++)
{
q->next[j]=NULL;
}
p->next[id]=q;
p=p->next[id];
}
else
{
p=p->next[id];
if(p->v||i==n-1) {flag=1;break;}
}
}
p->v=1;
}
int dele(tree *t)
{
if(t==NULL) return 0;
else
{
for(int i=0;i<MAX;i++)
{
if(t->next[i]!=NULL)
dele(t->next[i]);
}
}
free(t);
return 0;
}
int main()
{
int to;
scanf("%d",&to);
while(to--)
{
root=(tree *)malloc(sizeof(tree));      //动态申请内存
root->v=0;
for(int i=0;i<MAX;i++) root->next[i]=NULL;
int n;
flag=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",s);
if(!flag) creattree(s);
}
if(flag) printf("NO\n");
else printf("YES\n");
dele(root);
}
}








第二种是静态申请内存,也就是开个结构体数组,这种方法耗时最短,但是有个坏处就是如果题目没有告诉你要申请的结构体的数目,你开太少的话会RE,开太多容易爆掉,不过这种写法还是最普及的写法。(这种写法在POJ3630和HDU1671都能过)

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 10
const int N = 1000000;
char s[30];
bool flag;
typedef struct tree{
tree *next[MAX];
bool v;
};
tree dot[N],*bat;     ///申请结构体数组
tree *newNode()
{
tree *p = bat++;
for(int i=0;i<MAX;i++)
{
p->next[i]=NULL;
p->v=0;
}
return p;
}
tree *root;
void creattree(char *str)
{
tree *p=root,*q;
int n=strlen(str);
for(int i=0;i<n;i++)
{
int id=str[i]-'0';
if(p->next[id]==NULL)
{
q=newNode();
p->next[id]=q;
p=p->next[id];
}
else
{
p=p->next[id];
if(p->v||i==n-1) {flag=1;break;}
}
}
p->v=1;
}
void memin()
{
bat=dot;
root=newNode();
}
int main()
{
int to;
scanf("%d",&to);
while(to--)
{
memin();
int n;
flag=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",s);
if(!flag) creattree(s);
}
if(flag) printf("NO\n");
else printf("YES\n");
}
}

第三种方法为半动态申请,这种方法在处理上应该是最优的,既克服了动态申请内存时间太慢的缺点,又避免了静态申请内存数组大小不好控制的缺点。这种方法的原理就是一次性申请一个范围适中的结构体数组,比如这题可以开个10000,然后不够的时候再开,但是要把这些结构体给连上,最后拿来重新利用。实现方法如下:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 10
const int N = 10000;
char s[30];
bool flag;
typedef struct tree{
tree *next[MAX];
bool v;
};
tree *List;
tree *newNode()
{
if(List==NULL)				//如果10000个结构体用完可以继续申请
{
tree *p=new tree[10000];
for(int i=0;i<10000;i++)
{
p[i].next[0]=List;		///这里两行把结构体连接起来
List=p+i;			///
}
}
tree *p=List;
List=List->next[0];
for(int i=0;i<MAX;i++)
{
p->next[i]=NULL;
p->v=0;
}
return p;
}
tree *root;
void creattree(char *str)
{
tree *p=root,*q;
int n=strlen(str);
for(int i=0;i<n;i++)
{
int id=str[i]-'0';
if(p->next[id]==NULL)
{
q=newNode();
p->next[id]=q;
p=p->next[id];
}
else
{
p=p->next[id];
if(p->v||i==n-1) {flag=1;break;}
}
}
p->v=1;
}
void reuse(tree *o)			///退回去重新利用
{
if(o==NULL) return;
for(int i=0;i<MAX;i++)
{
reuse(o->next[i]);
}
o->next[0] = List;
List = o;
}
int main()
{
int to;
scanf("%d",&to);
while(to--)
{
root=newNode();
int n;
flag=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",s);
if(!flag) creattree(s);
}
if(flag) printf("NO\n");
else printf("YES\n");
reuse(root);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: