Phone List
题意:
给定一个整数 t ,表示测试案例数,每个测试案例给定一个整数 n ,接下来输入 n 行号码,判断这些号码中是否有某个号码是另一个号码的前缀,若有,则输出‘NO’,否则,输出’YES’。
数据范围:
1 <= t <= 40, 1 <= n <= 10000.
解题思路:
字典树
本题用字典树的常规做法即可解出,但有一点要注意,那就是后来输入的号码可能是前面某个号码的前缀
,所以在用字典树来解题之前,要先给每组的所有号码按长短排一下序
,短的在前,长的在后,这样就能保证后面判断的号码不可能是前面已判断的号码的前缀。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
using namespace std;
#define INF 0x3f3f3f
#define zero 1e-7
typedef long long ll;
const int N=1e5;
int tree[N][11];
bool endd[N];
int k;
struct node {
char s[15];
int len;
};
bool cmp(node x, node y) {
return x.len<y.len;
}
void init() {
k=0;
memset(tree, 0, sizeof(tree));
memset(endd, false, sizeof(endd));
return ;
}
bool judge(char *s) {
int len=strlen(s);
int p=0;
bool flag=true;
for(int i=0; i<len; i++) {
int c=s[i]-'0';
if(!tree[p][c])
tree[p][c]=++k;
p=tree[p][c];
if(endd[p]) flag=false;
}
endd[p]=true;
return flag;
}
int main() {
int t, n;
scanf("%d", &t);
while(t--) {
init();
scanf("%d", &n);
bool flag=true;
node number[10005];
for(int i=0; i<n; i++) {
scanf("%s", number[i].s);
number[i].len=strlen(number[i].s);
}
sort(number, number+n, cmp);//先给号码按长短排个序
for(int i=0; i<n; i++) {
if(!judge(number[i].s))
flag=false;
}
if(flag) printf("YES\n");
else printf("NO\n");
}
return 0;
}
来源:https://blog.csdn.net/Pandora_heart/article/details/98911678