这个题目可以用两种方法:首先都是将电话号码打成字典树,然后第一种方法就是记录下每次输入的号码,然后另外从头到尾将每一个电话号码都进行查找,看是否有前缀存在,这种方法无论从时间、空间都不优化,第二种方法相对好点,建树之时标记一下当前节点的下一个节点是否存在(当前串为之前串的前缀)以及是否有串在当前串之前就出现过(之前串是否为当前串的前缀),然后遍历查找时,每插入一个电话号码就对当前输入的电话号码进行查找,如果出现上述两种情况就可以判定为NO,PS:记得回收内存。。。
方法二:
#include <iostream>
using namespace std;
struct Trie
{
bool num;
bool end;
Trie *son[10];
Trie(){
for (int i = 0; i < 10; i ++){
son[i] = NULL;
}
end = num = false;
}
};
void insert(char *a, Trie *root)
{
int len = strlen(a);
Trie *temp = root;
for (int i = 0; i < len; i ++){
int k = a[i] - '0';
if (temp -> son[k] == NULL){
temp -> son[k] = new Trie;
}
temp -> num = true;
temp = temp -> son[k];
}
temp -> end = true;
}
char alp[11];
bool find(char *a, Trie *root)
{
Trie *temp = root;
int len = strlen(a);
int i;
for (i = 0; i < len; i ++){
int k = a[i] - '0';
if (temp -> end)return true;//如果之前有串为当前输入串的前缀
temp = temp -> son[k];
}
if (temp -> num)return true;//如果当前串为之前串的前缀
return false;
}
void dele(Trie *root)//记得回收内存,防止超内存
{
for (int i = 0; i < 10; i ++){
if (root -> son[i] != NULL){
dele(root -> son[i]);
}
}
free(root);
}
int main()
{
int t;
scanf("%d", &t);
while (t --){
int n1;
int n = 0;
scanf("%d", &n1);
getchar();
Trie *root;
root = new Trie;
bool check = false;
int st = false;
while (n1 --){
scanf("%s", alp);
if (!check){//如果WA,就写下这句话,因为check的true可能被之后的false覆盖掉导致错误
insert(alp, root);
check = find(alp, root);
}
}
if (check)printf("NO\n");
else printf("YES\n");
dele(root);
}
return 0;
}
方法一:
#include <iostream>
using namespace std;
struct Trie
{
int num;
int end;
Trie *son[26];
Trie(){
for (int i = 0; i < 26; i ++){
son[i] = NULL;
}
end = num = 0;
}
};
void insert(char *a, Trie *root)
{
int len = strlen(a);
Trie *temp = root;
for (int i = 0; i < len; i ++){
int k = a[i] - '0';//cout<<"asasd"<<endl;
if (temp -> son[k] == NULL){
temp -> son[k] = new Trie;
}
temp = temp -> son[k];
temp -> num ++;
}
temp -> end ++;
}
char alp[10010][11];
bool find(char *a, Trie *root)
{
Trie *temp = root;
int len = strlen(a);
int i;
for (i = 0; i < len; i ++){
int k = a[i] - '0';
int b = temp -> num;
int end = temp -> end;
temp = temp -> son[k];
if (b != temp -> num && end)return true;
}
return false;
}
void dele(Trie *root)
{
for (int i = 0; i < 10; i ++){
if (root -> son[i] != NULL){
dele(root -> son[i]);
}
}
free(root);
}
int main()
{
int t;
scanf("%d", &t);
while (t --){
int n1;
int n = 0;
scanf("%d", &n1);
getchar();
Trie *root;
root = new Trie;
while (n1 --){
scanf("%s", alp[n ++]);
insert(alp[n-1], root);
}
bool check = false;
for (int i = 0; i < n; i ++){
check = find(alp[i], root);
if (check)break;
}
if (check)printf("NO\n");
else printf("YES\n");
dele(root);
}
return 0;
}