题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1671
题面:
2 3 911 97625999 91125426 5 113 12340 123440 12345 98346
NO YES
是不是存在因为直接拨打某个号码,而无法拨打另一个号码的情况。是的话,输出“NO”,不是,输出“YES”。
解题:
构造字典树,然后查询每一条电话号码,一旦发现以某号码结尾的位置,该点val值大于1,输出NO。
代码:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; struct Trie { //ch数组存储每个节点的10个数字分别对应节点编号,没有为0,根节点为0 //小心 //第一维要乘以10,因为一个节点一个数字 int ch[100010][10]; //val数组一般用来存储权值,视题目灵活运用,sz是当前节点数量 int val[100010],sz; //初始化 void init() { sz=1; memset(ch,0,sizeof(ch)); } //插入一条单词 void insert(char *s) { //u是节点编号,并不是层数 int u=0,len=strlen(s); for(int i=0;i<len;i++) { //取下标 int c=(s[i]-'0'); //如果该节点不存在,创建该节点 if(!ch[u][c]) { //真的是相当的省 memset(ch[sz],0,sizeof(ch[sz])); //因为刚创建所以为1 val[sz]=1; //给该节点分配编号 ch[u][c]=sz++; //下移 u=ch[u][c]; } //已经存在了 else { //下移,并计数值加一 u=ch[u][c]; val[u]++; } } } //查询前缀 bool query(char *s) { int len=strlen(s),u=0,c; //不断下移,直至移到给定的前缀的最后一个单词 for(int i=0;i<len;i++) { c=s[i]-'0'; u=ch[u][c]; } if(val[u]>1) return true; else return false; } }; Trie T; char store[10010][12]; int main() { int n,t; scanf("%d",&t); bool flag=true; for(int i=1;i<=t;i++) { flag=true; scanf("%d",&n); T.init(); for(int j=0;j<n;j++) { getchar(); scanf("%s",store[j]); T.insert(store[j]); } for(int j=0;j<n;j++) { if(T.query(store[j])) { flag=false; break; } } if(flag) printf("YES\n"); else printf("NO\n"); } return 0; }