题目很简单
给定电话号码,然后看较短的号码是不是较长的号码的前缀,如果是的话就输出NO,否则就输出YES,当然相同也不可以存在,用普通写法一直超时。。。
每次用链表申请空间都很费时,以后最好用数组吧。。
代码如下
#include<cstdio>
#include<cstring>
//时间复杂度与单词长度有关
//空间复杂度最坏为单词长度总和*10
//自动补全可以用字典树完成
struct node{
int num;
node * next[10];
node(){
for (int i=0;i<10;i++)
next[i]=NULL;
num=0;
}
};
int c;
int l;
node *t;
bool insert(char s[],node* h){
t=h;
l=strlen(s);
for (int i=0;i<l;i++){
c=s[i]-'0';
if (t->next[c]==NULL) {
t->next[c]=new node(); //每次new浪费时间
t=t->next[c];
}
else {
t=t->next[c];
if (t->num!=0) return false;
}
}
t->num++;
for(int i=0;i<10;i++)
if (t->next[i]!=NULL)
return false;
return true;
}
void del(node *h){ //每次深搜释放空间同样耗费大量时间
if (h==NULL) return;
for (int i=0;i<10;i++){
if (h->next[i]!=NULL) {
del(h->next[i]);
}
}
delete h;
}
int main(){
int T;
scanf("%d",&T);
char s[11];
while(T--){
int n;
scanf("%d",&n);
node *head=new node();
bool f=true;
for (int i=0;i<n;i++){
scanf("%s",s);
//printf("%s\n",s);
if (f){
if (!insert(s,head)) f=false;
}
}
if (f) printf("YES\n");
else printf("NO\n");
del(head);
}
}
优化代码,给定空间大小,每次用之前清除,不用每次new 和delete,代码如下:
#include<cstdio>
#include<cstring>
//时间复杂度与单词长度有关
//空间复杂度最坏为单词长度总和*26
//自动补全可以用字典树完成
const int M=1000005;
struct node{
int num;
node * next[10];
node(){
for (int i=0;i<10;i++)
next[i]=NULL;
num=0;
}
}no[M];
int top;
int c;
int l;
node *t;
void del(node *h){
for (int i=0;i<10;i++)
h->next[i]=NULL;
h->num=0;
}
bool insert(char s[],node* h){
t=h;
l=strlen(s);
for (int i=0;i<l;i++){
c=s[i]-'0';
if (t->next[c]==NULL) {
del(&no[top]);
t->next[c]=&no[top];
top++;
t=t->next[c];
}
else {
t=t->next[c];
if (t->num!=0) return false;
}
}
t->num++;
for(int i=0;i<10;i++)
if (t->next[i]!=NULL)
return false;
return true;
}
int main(){
int T;
scanf("%d",&T);
char s[11];
while(T--){
int n;
scanf("%d",&n);
top=0;
del(&no[top]);
node *head=&no[top];
top++;
bool f=true;
for (int i=0;i<n;i++){
scanf("%s",s);
if (f){
if (!insert(s,head)) f=false;
}
}
if (f) printf("YES\n");
else printf("NO\n");
}
}