Phone List HDU - 1671(字典树)
Phone List HDU - 1671
题目链接:https://vjudge.net/problem/HDU-1671
题目:
给出一个电话号码列表,确定它是否一致,因为没有数字是另一个号码的前缀。 假设电话目录列出了这些数字:
1. Emergency 911
2. Alice 97 625 999
3. Bob 91 12 54 26
在这种情况下,无法呼叫Bob,因为只要您拨打了Bob的电话号码的前三位数字,中心就会将您的呼叫转接到紧急线路。 所以这个列表不一致。
输入
第一行输入给出一个整数,1 <= t <= 40,即测试用例的数量。 每个测试用例以n(电话号码的数量)在单独的行上开始,1 <= n <= 10000.然后是n行,每行有一个唯一的电话号码。 电话号码是最多十位数的序列。
产量
对于每个测试用例,如果列表一致则输出“YES”,否则输出“NO”。
思路:将这些电话号码插入字典树中,只要出现一个电话号码是另一个电话号码的前缀,那么就输出“NO”否则输出“YES”,
这题要注意内存的控制,否则会MLE,还有不能n方来利用find前缀函数判断每一个字符串在其他字符串是否是前缀,否则会TLE,
只要在将电话号码插入字典树的时候判断p->num是否不为0即可,如果不为0就break,很好的避免了n方判断、
// // Created by HJYL on 2019/8/20. // #include <iostream> #include <vector> #include <map> #include <string> #include <queue> #include <stack> #include <set> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> using namespace std; typedef long long ll; const int maxn=1e6+10; struct trie{ int sum; trie* next[10]; }*root; trie* build() { trie *T=(trie *)malloc(sizeof(trie)); T->sum=0; for(int i=0;i<10;i++) T->next[i]=NULL; return T; } bool flag; void insert(char* s) { trie* p=root; for(int i=0;s[i];i++) { if(p->next[s[i]-'0']==NULL) { p->next[s[i]-'0']=build(); } p=p->next[s[i]-'0']; if(p->sum!=0) { flag=false;//一旦出现前缀就跳出 break; } } p->sum++;//在字符串结尾,单词个数加一 for(int i=0;i<10;i++) { if(p->next[i]!=NULL) { flag=false; return; } } } int find(char* s) { trie* p=root; for(int i=0;s[i];i++) { if(p->next[s[i]-'0']==NULL) return 0; else p=p->next[s[i]-'0']; } return p->sum; } void delte(trie *p)//很最重要的内存删除 { if(p!=NULL) { for(int i = 0; i < 10; i++) { if(p->next[i]!=NULL) delte(p->next[i]); } } free(p); p=NULL; } int main() { //freopen("C:\\Users\\asus567767\\CLionProjects\\untitled\\text", "r", stdin); int T,n; scanf("%d",&T); while(T--) { scanf("%d",&n); root=build(); char str[10007][50]; flag=true; for(int i=0;i<n;i++) { scanf("%s",str[i]); insert(str[i]); } if(flag) { printf("YES\n"); delte(root); } else { printf("NO\n"); delte(root); } } return 0; }