题目链接:Phone List
思路:字典树模板题。不需要用到Search函数,用全局变量flag标记结果输出YES还是NO。当一个字符串在参与建Trie树时,走过的路上的点有isStr标记为true就证明此前参与建Trie树的一个字符串是当前串的前缀;还有当前参与建Trie树的串,最后一个字符所在的节点,它有子节点证明当前串是某串前缀。分别处理一下两种情况:如样例中,先输入911,后输入91 12 54 26 与先输入 91 12 54 26 后输入 911 处理方式不同。详见代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#include<cstdlib>
#define mem(a,b) memset(a,b,sizeof(a))
#define INF 0x7fffffff
typedef long long ll;
using namespace std;
const int maxn = 1e4+10;
const int MAX = 10;
struct Trie{
bool isStr;
Trie *next[MAX];
};
bool flag;
void BuildTrie(Trie *root, const char *s){
if(root == NULL || *s == '\0'){
return;
}
int i;
Trie *p = root;
while(*s != '\0'){
if(p -> next[*s - '0'] == NULL){
Trie *tmp = (Trie *)malloc(sizeof(Trie));
for(int i = 0; i < MAX; i++){
tmp -> next[i] = NULL;
}
tmp -> isStr = false;
p -> next[*s - '0'] = tmp;
p = p -> next[*s - '0'];
}else if(p -> next[*s - '0'] != NULL){
p = p -> next[*s - '0'];
if(*(s+1) == '\0'){
flag = false;
return;
}
if(p -> isStr == true){
flag = false;
return;
}
}
s++;
}
p -> isStr = true;
}
void dele(Trie *root){
int i;
for(int i = 0; i < MAX; i++){
if(root -> next[i] != NULL){
dele(root -> next[i]);
}
}
free(root);
}
//int Search(Trie *root,const char *s){
// Trie *p = root;
// while(p != NULL && *s != '\0'){
// p = p -> next[*s - 'a'];
// s++;
// }
// return (p != NULL && p -> isStr == true);
//}
int main(){
int T,i;
scanf("%d",&T);
while(T--){
int n;
char s[maxn];
Trie *root = (Trie *)malloc(sizeof(Trie));
for(int i = 0 ;i < MAX; i++){
root -> next[i] = NULL;
}
root -> isStr = false;
flag = true;
scanf("%d",&n);
getchar();
for(int i = 0; i < n; i++){
scanf("%s",s);
if(flag)
BuildTrie(root,s);
}
if(flag) puts("YES");
else puts("NO");
dele(root);
}
return 0;
}