CodeForces 858D Polycarp's phone book(Trie)
来源:互联网 发布:数据对比分析的方法 编辑:程序博客网 时间:2024/05/24 06:48
Polycarp's phone book
time limit per test:4 seconds
memory limit per test:256 megabytes
input:standard input
output:standard output
There are n phone numbers in Polycarp's contacts on his phone. Each number is a 9-digit integer, starting with a digit different from0. All the numbers are distinct.
There is the latest version of Berdroid OS installed on Polycarp's phone. If some number is entered, is shows up all the numbers in the contacts for which there is a substring equal to the entered sequence of digits. For example, is there are three phone numbers in Polycarp's contacts: 123456789, 100000000 and 100123456, then:
- if he enters 00 two numbers will show up: 100000000 and 100123456,
- if he enters 123 two numbers will show up 123456789 and 100123456,
- if he enters 01 there will be only one number 100123456.
For each of the phone numbers in Polycarp's contacts, find the minimum in length sequence of digits such that if Polycarp enters this sequence, Berdroid shows this only phone number.
The first line contains single integer n (1 ≤ n ≤ 70000) — the total number of phone contacts in Polycarp's contacts.
The phone numbers follow, one in each line. Each number is a positive 9-digit integer starting with a digit from1 to9. All the numbers are distinct.
Print exactly n lines: the i-th of them should contain the shortest non-empty sequence of digits, such that if Polycarp enters it, the Berdroid OS shows up only thei-th number from the contacts. If there are several such sequences, print any of them.
3123456789100000000100123456
900001
4123456789193456789134567819934567891
21938191
大致题意,给出很多个号码,然后要你对每一个号码找出一个长度最短的识别码,即长度最短的同时,只有那一个电话包含这个识别码。
这里队友机智无比,直接想到用字典树搞。由于号码最多只有10位,所以对于每一个号码,在字典树里面分别加入第0位~最后一位,第1位~最后一位,第2位~最后一位……这样解决了字典树只能一定要从头开始的缺陷。如此一来对于一个号码的任意一个小段,我们都可以对应在字典树中找到一个从根开始的路径与之对应。那么我们要做的就是统计一直到任意小段的最后一位的节点,有多少个这样的子串包含这个小段。如果只有一个包含这个小段,那么这个小段可以作为特征码。对于这个小段,由于长度较短,我们直接进行枚举即可,logN判断。
这样子写了之后,发现样例过不了……我们观察第一个样例的第二个号码1000000000,注意到我们加入字典树的时候,加入了很多个只含有0的子串,那么在我们判断的时候,对于000这个合法的特征码,在字典树中查询的时候出来会显示多个匹配的串。实际上,这些只含有0的串都是统一号码提供的,并不应该被统计进去。那么就有一个新的问题,如何判定哪些要统计。这时,我有机智的脑补,直接加一个时间戳就行了,对于每一个点,我都加一个时间戳,表示该点是被哪一个号码更新的,如果是统一号码,那么在统计size的时候就不把这个统计进去,否则统计。巧妙地解决了这个问题。具体见代码:
#include <bits/stdc++.h>#define N 100010using namespace std;struct Trie{ struct node{int size,ch[10],t;}T[N<<5]; int tot,root; void init() { tot=root=1; memset(T,0,sizeof(T)); } void ins(char* x,int t)//t为时间戳 { int o=root; if (T[o].t!=t){T[o].size++;T[o].t=t;}//如果时间戳不相同则增加,否则不 for(int k=0;k<strlen(x);k++) { int c=x[k]-48; if(!T[o].ch[c]) T[o].ch[c]=++tot; o=T[o].ch[c]; if (T[o].t!=t){T[o].size++;T[o].t=t;} } } int query(char* x) { int o=root; for(int k=0;k<strlen(x);k++) { int c=x[k]-48; o=T[o].ch[c]; } return T[o].size; }} Trie;char str[N][10],s[10];int n;int main(){ scanf("%d\n",&n); for(int i=1;i<=n;i++) { scanf("%s",str[i]); for(int j=0;j<strlen(str[i]);j++) { strcpy(s,str[i]+j);//把每一位到最后的子串加到字典树中 Trie.ins(s,i); } } for(int i=1;i<=n;i++) { bool flag=0; for(int len=1;len<=strlen(str[i]);len++) { for(int b=0;b+len-1<strlen(str[i]);b++) { memset(s,0,sizeof(s)); for(int j=0;j<len;j++) s[j]=str[i][j+b];//暴力枚举特征码,从短的开始枚举 if (Trie.query(s)==1) {flag=1;break;}//如果只出现一次,那么合法,直接输出 } if (flag) {printf("%s\n",s); break;} } } return 0;}
- CodeForces 858D Polycarp's phone book(Trie)
- Codeforces 861 D. Polycarp's phone book (trie)
- codeforces 858D Polycarp's phone book(字典树)
- CodeForces 858C Did you mean... 、 CodeForces 858D Polycarp's phone book!黑科技
- Codeforces Round #434 D. Polycarp's phone book (字典树)
- Codeforces Round #434 (Div. 2): D. Polycarp's phone book(字典树)
- Codeforces 861 D Polycarp's phone book(字典树模板)
- 858D Polycarp's phone book 字典树
- codeforce 858D Polycarp's phone book(字典树)
- Codeforces Round #434 Polycarp's phone book (字典树)
- Polycarp's phone book
- Codeforces Round #434 (Div. 2) D Polycarp's phone book(字符串,字典树)
- Codeforces858D Polycarp's phone book
- cf434 B. Polycarp's phone book
- Codeforces Round #434 (Div. 2, )-字典树&好题&板子-Polycarp's phone book
- Codeforces 706D-Vasiliy's Multiset(Trie树)
- codeforces 589C Polycarp's Masterpiece(分治 折半搜索)
- codeforces 589 C. Polycarp's Masterpiece
- Linux下文件权限掩码 umask
- android configChanges属性 ==> 生命周期
- [Python]网络爬虫(二):利用urllib2通过指定的URL抓取网页内容
- 线下活动【西安站】用Leangoo做Scrum敏捷开发实战课(免费)
- http和https的区别
- CodeForces 858D Polycarp's phone book(Trie)
- codeforces 100959B Airports 曼哈顿距离最大生成树
- POJ
- CS R25 C(BFS+二维前缀和) D(好题,合理枚举+树状数组维护) E(建图,连通分量,割点)
- 关于C和C++中static关键字的详解
- number 二分答案
- 【模板】欧拉筛
- Python3 数据结构
- Wooden Sticks