题目链接:Phone List
题目大意:每组数据给n个号码,假设某一个电话号码恰好是另一个电话号码的前缀,那么这组案例是失败的,输出No,因为它不能保证每个电话都能拨打出去。题目本质就是寻找一个字符串是否恰好是另一字符串的前缀,若是,则输出NO
代码如下:
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int siz=100005;
int rt,sig;
char s[15];
int num[siz];
int tr[siz][15];
void in(){
int u=0;
for(int i=0;s[i];i++){
if(tr[u][s[i]-'0']==0)
tr[u][s[i]-'0']=rt++;
u=tr[u][s[i]-'0'];
}
num[u]++;
}
void get(){
int u=0;
for(int i=0;s[i];i++){
if(tr[u][s[i]-'0']==0)
return;
if(num[tr[u][s[i]-'0']]!=0){
sig=1;// ?
return;
}
u=tr[u][s[i]-'0'];
// printf("u2:%d\n",u);
}
sig=1;
}
int main(){
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
memset(tr,0,sizeof(tr));
memset(num,0,sizeof(num));
rt=1,sig=0;
for(int i=1;i<=n;i++){
scanf("%s",s);
if(sig)
continue;
// break;
get();
in();
}
if(sig)
printf("NO\n");
else
printf("YES\n");
}
return 0;
}
代码分析:
这里代码利用的是数组模拟解决字典树问题。
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int siz=100005;
int rt,sig;
char s[15];
int num[siz];
int tr[siz][15];//siz处出现的字母
void in(){//插入
int u=0;
for(int i=0;s[i];i++){
if(tr[u][s[i]-'0']==0)//现在插入的字母在之前节点处未出现过 错 //现在插入的字母在之前数组的对应位置未出现过
tr[u][s[i]-'0']=rt++;//字母插入一个新的位置,否则不做处理 错 //此处插入了一个元素,数组下标后移
u=tr[u][s[i]-'0'];//为下个字母的插入做准备
}//u上节点编号,rt下节点编号
//按输入顺序编号? 错
num[u]++; //以谁为前缀,个数储存 错
//对每一字符串,某一位置的字符在之前字符串的对应位置是否统计过 错
//对于数组的第u个位置处,出现了几种字符 错
//对于某一字符串它的长度是多少
//printf("u1:%d %d\n",u,num[u]);
}
void get(){//查找
int u=0;
for(int i=0;s[i];i++){
/*main函数先进入get()函数,对于这个字符串中的每一个元素,假设这个元素没有出现,
就返回到main函数中,进入in()函数中,对个字符串进行赋值操作
*/
if(tr[u][s[i]-'0']==0)//以u为头结点的x字母不存在
return;
if(num[tr[u][s[i]-'0']]!=0){//此节点已被使用 //证明有前缀 //当前串全走的之前的结点
sig=1;// ?
return;//return 到哪去
}
u=tr[u][s[i]-'0'];//为查询下个字母做准备
// printf("u2:%d\n",u);
} //如果走到之前某个串的结尾,或者
sig=1;
//当前串全走的之前的节点则直接标记
}
int main(){
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
memset(tr,0,sizeof(tr));
memset(num,0,sizeof(num));
rt=1,sig=0;
for(int i=1;i<=n;i++){
scanf("%s",s);
if(sig) //sig==1代表有子串 //如果这个字符串已经有了子串就不需要再进行接下里的操作了
//continue;
break;
get();
in();
}
if(sig)
printf("NO\n");
else
printf("YES\n");
}
return 0;
}