给定 个长度不超过 的数字串,问其中是否存在两个数字串 ,使得 是 的前缀,多组数据。
输入格式
第一行一个整数 ,表示数据组数。
对于每组数据,第一行一个数 ,接下来 行输入 个数字串。
输出格式
对于每组数据,若存在两个数字串 ,,使得 是 的前缀,则输出 NO ,否则输出 YES 。
请注意此处结果与输出的对应关系!
样例输入
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
样例输出
NO
YES
数据范围与提示
对于100%的数据 ,1<=T<=40,1<=n<=1e4
字典树模板 刚开始把tot=1放在全局变量,我以为这样也可以每次循环tot=1,后来发现tot=1必须放在主函数里
判断某个两个数字串S,T,S是否是T的前缀
1.当字符串遍历完,依然没有新建结点
2.遍历到串结尾标记
//若当前串插入后没有新建任何结点;当前串是之后串的前缀
//经过带有串结尾标记,则之前是当前前缀
#include <stdio.h>
#include <string.h>
using namespace std;
const int maxn = 1e5 + 10;
int tot; //结点信息
int ch[maxn][20];
bool bo[maxn]; //标记尾结点
char a[20];
bool insert(char *s) //插入一个字符串
{
int u = 1; //根结点
int len = strlen(s);
// int i;
bool flag = false;
for (int i = 0; i < len; i++) {
int c = s[i] - '0';
if (!ch[u][c])
ch[u][c] = ++tot;
else if (i == len - 1) //注意这里是else if 即当ch[u][c]==0&&i==len-1
flag = true;
u = ch[u][c];
if (bo[u])
flag = true; //经过的节点带有串结尾标记
}
// if(i==len) //遍历完了,依然没有新建结点
// flag=true;
bo[u] = true; //尾结点标记
return flag;
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n;
scanf("%d", &n);
tot = 1;
memset(ch, 0, sizeof(ch));
memset(bo, false, sizeof(bo));
int k = 0;
while (n--) {
scanf("%s", a);
if (insert(a))
k = 1;
else
continue;
}
if (k)
printf("NO\n");
else
printf("YES\n");
}
return 0;
}