Phone List
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:
1. Emergency 911
2. Alice 97 625 999
3. 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.
InputThe 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.OutputFor each test case, output “YES” if the list is consistent, or “NO” otherwise.Sample Input
1. Emergency 911
2. Alice 97 625 999
3. 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.
2 3 911 97625999 91125426 5 113 12340 123440 12345 98346Sample Output
NO YES
字典树的入门题,当然直接字符串匹配应该也是能做出来。在写这道题之前我们先来学习下字典树Trie
附上博客:http://blog.youkuaiyun.com/bbbblzy/article/details/78757037
前缀树还是很好理解,我们按照输入的顺序,建树。这个题是数字,0~9,我们就只需要开10个分叉。
题目意思:我们需要判断一个电话号码是不是其他的前缀。具体注释见代码
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<queue>
#include<vector>
#include<stack>
#include<list>
using namespace std;
const int INF =100100+5;
const int maxn = 110010+5//切记数组开大10倍
int trie[maxn][10];//静态字典树
int f[maxn];//染色
bool flag;
int cnt;
char s[12];
void _insert()
{
int i;
int len=strlen(s+1);
int tem=0;
for(i=1; i<len; i++)
{
if(!trie[tem][s[i]-'0']) trie[tem][s[i]-'0']=++cnt;//移动
tem=trie[tem][s[i]-'0'];
if(f[tem]) flag=false;// 在移动过程中 判断其他字符串是不是这个字符串前缀
}
if(trie[tem][s[len]-'0']) flag=false;//单独判断 这个单词是否为其他单词前缀
else trie[tem][s[len]-'0']=++cnt;
f[trie[tem][s[len]-'0']]=1;//染色 代表这个单词出现过 详细见上面推荐的字典树博客
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
flag=true;
cnt=0;
memset(f,0,sizeof(f));
memset(trie,0,sizeof(trie));
for(int i=1; i<=n; i++)
{
scanf("%s",s+1);
if(flag) _insert();//这里如果出现过前缀了我们没必要在加入字典树了 已经达到题目的要求
}
if(flag) printf("YES\n");//出现了
else printf("NO\n");
}
}
/* 字典树特性 比较突出的就是消耗空间换时间*/
Shortest Prefixes
A prefix of a string is a substring starting at the beginning of the given string. The prefixes of "carbon" are: "c", "ca", "car", "carb", "carbo", and "carbon". Note that the empty string is not considered a prefix in this problem, but every non-empty string is considered to be a prefix of itself. In everyday language, we tend to abbreviate words by prefixes. For example, "carbohydrate" is commonly abbreviated by "carb". In this problem, given a set of words, you will find for each word the shortest prefix that uniquely identifies the word it represents.
In the sample input below, "carbohydrate" can be abbreviated to "carboh", but it cannot be abbreviated to "carbo" (or anything shorter) because there are other words in the list that begin with "carbo".
An exact match will override a prefix match. For example, the prefix "car" matches the given word "car" exactly. Therefore, it is understood without ambiguity that "car" is an abbreviation for "car" , not for "carriage" or any of the other words in the list that begins with "car".
Input
In the sample input below, "carbohydrate" can be abbreviated to "carboh", but it cannot be abbreviated to "carbo" (or anything shorter) because there are other words in the list that begin with "carbo".
An exact match will override a prefix match. For example, the prefix "car" matches the given word "car" exactly. Therefore, it is understood without ambiguity that "car" is an abbreviation for "car" , not for "carriage" or any of the other words in the list that begins with "car".
The input contains at least two, but no more than 1000 lines. Each line contains one word consisting of 1 to 20 lower case letters.
Output
The output contains the same number of lines as the input. Each line of the output contains the word from the corresponding line of the input, followed by one blank space, and the shortest prefix that uniquely (without ambiguity) identifies this word.
Sample Input
carbohydrate cart carburetor caramel caribou carbonic cartilage carbon carriage carton car carbonateSample Output
carbohydrate carboh cart cart carburetor carbu caramel cara caribou cari carbonic carboni cartilage carti carbon carbon carriage carr carton carto car car carbonate carbona
题目大概意思:输出唯一前缀,输入以文件结束输入。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<queue>
#include<vector>
#include<stack>
#include<list>
using namespace std;
const int maxn=10000+10;
int trie[maxn][35];
char s[maxn][35];
int in[maxn];
int cnt=0;
int n=1;
void _insert(char *a)
{
int temp=0;
int len=strlen(a);
for(int i=0; i<len; i++)
{
in[temp]++;
if(!trie[temp][a[i]-'a']) trie[temp][a[i]-'a']=++cnt;
temp=trie[temp][a[i]-'a'];
}
in[temp]++;//这里要自增
}
void Find(char *a)
{
int len=strlen(a);
int temp=0;
for(int i=0; i<len; i++)
{
//cout<<temp<<" "<<in[temp]<<endl;
if(in[temp]==1)//等于1的时候代表 就只有它这个字符串出现过到这里 直接退出了
break;
printf("%c",a[i]);
temp=trie[temp][a[i]-'a'];//更新单词的下一个点
}
}
int main()
{
while(scanf("%s",s[n])==1)
{
_insert(s[n]);
n++;
}
n--;
for(int i=1; i<=n; i++)
{
printf("%s ",s[i]);
Find(s[i]);
printf("\n");
}
}