给出一个电话列表,如果列表中存在其中一个号码是另一个号码的前缀这一情况,那么就称这个电话列表是不兼容的。
假设电话列表如下:
Emergency 911
Alice 97 625 999
Bob 91 12 54 26
在此例中,报警电话号码(911
)为 Bob 电话号码(91 12 54 26
)的前缀,所以该列表不兼容。
此题需要判断:
1.是否存在一个字符串是当前字符串的前缀--> strlen(当前)> strlen(之前):是否创建当前字符串时发现了结束标志。
2.当前字符串是否是某个字符串的前缀--> strlen(当前)< strlen(之前):是否能够检索到当前字符串-->没有构建新的节点!
#include <bits/stdc++.h>
using namespace std;
int t ,n ,que;//组 个数 序号
char s[11] ;// 存储电话号码
int trie[100010][11] ,js[100010];//前缀树【节点】【号】 记录结束位置
bool insert(char* s)//插入字符串/构建前缀树
{
int p = 0;
bool jsl = false ;//1.遍历路径时是否发现了结束标志 0否 {1是}
bool new_jd = false ;//2.便利路径时是否创建了新的节点 0否 {1是}
for(int i = 0 ; s[i] ; i ++)
{
int ss = s[i] - '0' ;
if(!trie[p][ss])//没有这个节点,构建节点
{
trie[p][ss] = ++ que;
new_jd = true ;
}
p = trie[p][ss] ;
if(js[p]) jsl = true ;//发现了结束标记(判断1)
}
js[p] = true ;//标记当前字符串的结束位置
return jsl || !new_jd ;
}
int main ()
{
cin >> t ;
while(t--)
{
cin >> n ;
que = 0 ;
memset(trie,0,sizeof trie) ;//每一组数据要初始化
memset(js ,0 ,sizeof js) ;
bool pd = true ;
for(int i = 0 ; i < n ; i ++)
{
cin >> s;
//不兼容(有前缀):1.发现结束标志--》jsl == 1
//或者2.没有创建新的节点--》new_jd == 0
if(insert(s)) pd = false ;//判断是否为有前缀-不兼容
}
if(pd) cout << "YES" << endl ;//兼容
else cout << "NO" << endl ;//不兼容
}
return 0;
}
前缀树:init(初始化),insert(插入):前缀树的构建,注意字符串结束要标记,query(查询):查询部分,查询是否有这个字符串。