题意:给定若干电话号码,如果没有号码是其他号码的前缀,则输出YES,否则输出NO
思路:使用Trie树(字典树),用flag域标定当前节点是否为一个电话号码的末位。直接分配空间。
输入:
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
输出:
NO
YES
#include <stdio.h>
#include <string.h>
#define N 100005
char s[11];
typedef struct node{
struct node* next[10];
int flag;
}tree;
tree t[N];
tree *alloc,*root;
int T,n;
void init(){
int i;
alloc = t;
root = alloc++;
root->flag = 0;
for(i = 0;i<10;i++)
root->next[i] = NULL;
}
int insert(){
int i,j,flag = 0;
tree *p,*q;
p = root;
for(i = 0;s[i]!='\0';i++){
if(p->next[s[i]-'0']!=NULL){
if(p->next[s[i]-'0']->flag == 1)//说明存在一个号码是当前号码的前缀
return 0;
}else{
flag = 1;//如果插入过程中建立了新节点,则当前号码必成立;否则说明当前号码是另一个号码的前缀
q = alloc++;
for(j = 0;j<10;j++)
q->next[j] = NULL;
if(s[i+1]!='\0')
q->flag = 0;
else
q->flag = 1;
p->next[s[i]-'0'] = q;
}
p = p->next[s[i]-'0'];
}
if(!flag)
return 0;
return 1;
}
int main(){
freopen("a.txt","r",stdin);
scanf("%d",&T);
while(T--){
int flag = 0;
init();
scanf("%d",&n);
while(n--){
scanf("%s",s);
if(flag)
continue;
if(!insert())
flag = 1;
}
if(flag)
printf("NO\n");
else
printf("YES\n");
}
return 0;
}
insert中,可以使用另一种方式判断当前号码是否为之前号码的前缀,略去flag判变量
int insert(){
int i,j;
tree *p,*q;
p = root;
for(i = 0;s[i]!='\0';i++){
if(p->next[s[i]-'0']!=NULL){
if(p->next[s[i]-'0']->flag == 1)//说明存在一个号码是当前号码的前缀
return 0;
if(s[i+1] == '\0')//说明当前号码是另一个号码的前缀
return 0;
}else{
q = alloc++;
for(j = 0;j<10;j++)
q->next[j] = NULL;
if(s[i+1]!='\0')
q->flag = 0;
else
q->flag = 1;
p->next[s[i]-'0'] = q;
}
p = p->next[s[i]-'0'];
}
return 1;
}
2016-10-7写的另一个版本:
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <vector>
#include <queue>
#include <algorithm>
#include <cmath>
#include <map>
#include <iostream>
#define N 6005
#define INF 0x3fffffff
using namespace std;
struct trie{
bool flag;
trie *next[10];
trie():flag(false){
memset(next, 0, sizeof(next));
}
void clear(){
flag = false;
memset(next, 0, sizeof(next));
}
}t[100005],*root,*alloc;
bool search(trie *root,string str){
bool hasnew = false;
int len = str.size();
for(int i = 0;i<len;i++){
if(root->next[str[i]-'0']){
if(root->next[str[i]-'0']->flag)
return false;
}else{
hasnew = true;
alloc++;
alloc->clear();
root->next[str[i]-'0'] = alloc;
}
root = root->next[str[i]-'0'];
}
root->flag = true;
return hasnew;
}
int main(){
int T,n;
scanf("%d",&T);
while(T--){
string str;
bool res = true;
root = alloc = t;
root->clear();
scanf("%d",&n);
for(int i = 0;i<n;i++){
cin >> str;
if(res)
res = search(root,str);
}
if(res)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}