题目大意:如果一个号码,是另一个号码的前缀的话,就输出“NO” 否则输出“YES”
解题思路:用字典树存储,然后在判断能否拨号
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
const int maxn = 10;
using namespace std;
bool is_phone ; //判断是否能拨打电话号码
typedef struct TrieNode
{
bool flag ; // 在字符串最后的标记
struct TrieNode *next[maxn];
} Trie;
Trie *root;
Trie *new_set() //新建结点
{
Trie *p = (Trie *)malloc(sizeof(Trie));
for(int i = 0 ; i < maxn ; i ++)
{
p->next[i] = NULL;
}
p->flag = false ;
return p;
}
void Insert(char *str) //建立字典树
{
Trie *p;
p = root;
int len = strlen(str);
for(int i = 0 ; i < len ; i ++)
{
if(p->next[str[i] - '0'] == NULL) //如果没有建立过结点
{
if(p->flag == false)
{
p->next[str[i] - '0'] = new_set(); //建立新的结点
p = p->next[str[i] - '0'];
if( i == len -1) //到达字符串末尾
p->flag = true;
else
p->flag = false;
}
else //当前字符更长,覆盖了以前的串 ,不能拨号
{
is_phone = false ;
return ;
}
}
else //当前号码为以前字符串的前缀 , 不能拨号
{
if(i == len-1 && p->flag == false)
{
is_phone = false;
return ;
}
p = p->next[str[i] - '0'];
}
}
return ;
}
int Delete(Trie *temp) //释放内存
{
if(temp == NULL)
return 0;
for(int i = 0 ; i < maxn ; i ++)
{
if(temp->next[i] != NULL)
{
Delete(temp->next[i]);
}
}
free(temp);
return 0;
}
int main()
{
//freopen("in.txt","r",stdin);
int ncase , n , i ;
char str[1010];
cin>>ncase;
while(ncase--)
{
is_phone = true ;
root = new_set();
cin>>n;
for(i = 0 ; i < n ; i ++)
{
cin>>str;
Insert(str);
}
if(is_phone)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
Delete(root);
}
return 0;
}