这道题目依旧是 字典树题目
大意:
目前有 t 组数据, n 个电话号码,如果拨打号码的时候 先拨通了某个号码,那么这一串号码就无法全部拨通,
举个例子 911 和 9112016652 相比 后者就无法被拨通,因为 911 会先被拨通。
如果都可拨通 输出 YES 不然输出 NO
这道题意思很明确,给你 n 个字符串,每个字符串都不能是另外一个的前缀,这里我们只需要每个字符串结尾的时候 对其做一个标记,之后 对于每个新的字符串,我们遍历 从0 --- n-2位,如果发现阶数标记,那么就不能全部拨同,否则就可以。
稍微改动一下 find 和 insert 函数就可以了。
以下 为 AC 代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e5+5;
int tree[maxn][30];
int flag[maxn];
int tot;
void _insert(char *str)
{
int rt=0;
int len = strlen(str);
for(int i=0; i<len; i++)
{
int id = str[i] - '0';
if(!tree[rt][id])
tree[rt][id]=++tot;
rt = tree[rt][id];
}
flag[rt] = 1;
}
bool _find(char *str)
{
int rt=0;
int len = strlen(str);
for(int i=0; i<len-1; i++)
{
int id = str[i] - '0';
rt = tree[rt][id];
if(flag[rt])
return false;
}
return true;
}
char ss[maxn][30];
int main()
{
int n,t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(flag,0,sizeof(flag));
memset(tree,0,sizeof(tree));
tot=0;
for(int i=0;i<n;i++)
{
scanf("%s",ss[i]);
_insert(ss[i]);
}
int cnt=1;
for(int i=0;i<n;i++)
{
if(!_find(ss[i]))
{
cnt=0;
break;
}
}
if(cnt)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}