Phone List 字典树 OR STL
Phone List
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 140 Solved: 35
Description
Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let’s say the phone catalogue listed these numbers:
- Emergency 911
- Alice 97 625 999
- Bob 91 12 54 26
In this case, it’s not possible to call Bob, because the central would direct your call to the emergency line as soon as you had dialled the first three digits of Bob’s phone number. So this list would not be consistent.
Input
The first line of input gives a single integer, 1<=t<=40, the number of test cases. Each test case starts with n, the number of phone numbers, on a separate line, 1<=n<=10000. Then follows n lines with one unique phone number on each line. A phone number is a sequence of at most ten digits.
Output
For each test case, output “YES” if the list is consistent, or “NO” otherwise.
Sample Input
2 3 911 97625999 91125426 5 113 12340 123440 12345 98346
Sample Output
NO YES
题意:查询n个字符串,是否存在一个字符串是其他字符串的前缀。
秒想到字典树,撸模版AC了,然后和队友交流,学长说我写的太复杂了,直接用set写就行了。我后面试这写了一下,但是一直超时,各种优化实在出不来,问了下学长,了解了新操作,涨知识了了。
字典树法:
#include "cstdio" #include "cstring" #include "iostream" #include "algorithm" #include "cmath" using namespace std; #define memset(x,y) memset(x,y,sizeof(x)) const int MX = 1e6 + 5; struct Trie{ int v; Trie *next[11]; }root; void Build(char *s){ int len = strlen(s); Trie *p=&root,*q; for(int i=0;i<len;i++){ int num=s[i]-'0'; if(p->next[num]==NULL){ q=(Trie *)malloc(sizeof (root)); q->v=1; for(int j=0;j<11;j++){ q->next[j]=NULL; } p->next[num]=q; p=p->next[num]; }else { p=p->next[num]; p->v++; } } } int Query(char *s){ int len = strlen(s); Trie *p=&root; for(int i=0;i<len;i++){ int num=s[i]-'0'; if(p->next[num]==NULL){ return 0; } else{ p=p->next[num]; } } int v=p->v; return v; } char s[10005][20]; int n,T; int main(){ cin>>T; while(T--){ memset(s,0); for(int i=0; i<11; i++)root.next[i]=NULL; cin>>n; int ans=0; for(int i=0;i<n;i++){ cin>>s[i]; Build(s[i]); } for(int i=0;i<n;i++){ ans+=Query(s[i])-1; } if(ans>0)puts("NO"); else puts("YES"); } return 0; } /********************************************************************** Problem: 1886 User: HDmaxfun Language: C++ Result: AC Time:304 ms Memory:114092 kb **********************************************************************/
树状数组:
#include "cstdio" #include "cstring" #include "string" #include "iostream" #include "algorithm" using namespace std; #define memset(x,y) memset(x,y,sizeof(x)) struct Trie { int v; int next[11]; void init() { memset(next,-1); v=1; } } dir[100005]; int tot; void Build(char s[]) { int len = strlen(s); int now=0; for(int i=0; i<len; i++) { int num=s[i]-'0'; if(dir[now].next[num]==-1) { tot++; dir[tot].init(); dir[now].next[num]=tot; now=dir[now].next[num]; } else { now=dir[now].next[num]; dir[now].v++; } } } int Query(char s[]) { int len = strlen(s); int now=0; for(int i=0; i<len; i++) { int num=s[i]-'0'; //cout <<num; if(dir[now].next[num]==-1) return 0; else now=dir[now].next[num]; } return dir[now].v; } char s[10005][20]; int n,T; int main() { cin>>T; while(T--) { memset(s,0); memset(dir,0); tot=0; dir[0].init(); cin>>n; int ans=0; for(int i=0; i<n; i++) { cin>>s[i]; Build(s[i]); } for(int i=0; i<n; i++) { ans+=Query(s[i])-1; // puts(""); //cout <<s[i]<<" "<<ans<<endl; } if(ans>0)puts("NO"); else puts("YES"); } return 0; }
set:
#include "cstdio" #include "string" #include "cstring" #include "iostream" #include "algorithm" #include "cmath" #include "set" using namespace std; #define memset(x,y) memset(x,y,sizeof(x)) const int MX = 1e4 + 5; string a[MX]; set <string> st; int main() { int T,n; char s[15]; cin>>T; while(T--) { scanf("%d",&n); st.clear(); int ans=true; for(int i=0; i<n; i++)scanf("%s",s),a[i]=string(s); sort(a,a+n); for(int i=n-1; i>=0; i--) { if(st.find(a[i])!=st.end()){ ans=false; break; } string tem=""; int len=a[i].length(); for(int j=0;j<len;j++){ tem+=a[i][j]; //string 居然可以直接添加字符,涨知识了。网上查了一下,string是一种类对象,可以直接用 +"xxx"将xxx直接接在前一个对象尾部。 st.insert(tem); } } puts(ans?"YES":"NO"); } return 0; } //我一开始一直在一个个字符的添加成串,再转到set里面,这种方法卡时间又卡这么厉害,之前没过也是必然了。。 /********************************************************************** Problem: 1886 User: HDmaxfun Language: C++ Result: AC Time:972 ms Memory:7460 kb **********************************************************************/