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写就行了。我后面试这写了一下,但是一直超时,各种优化实在出不来,问了下学长,了解了新操作,涨知识了了。

第一个是set写的,下面这个是字典树写的,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<26; 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
**********************************************************************/

  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
**********************************************************************/

  

				
时间: 2024-10-14 09:28:35

Phone List 字典树 OR STL的相关文章

HDU 1800 Flying to the Mars 字典树,STL中的map ,哈希树

http://acm.hdu.edu.cn/showproblem.php?pid=1800 字典树 #include<iostream> #include<string.h> #include<stdio.h> using namespace std; struct node { int sum; node *next[10]; node() { sum=0; memset(next, NULL, sizeof(next)); }; }; int ans; char

STL 之map解决 Message Flood(原字典树问题)

Message Flood Time Limit:1500MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Description Well, how do you feel about mobile phone? Your answer would probably be something like that "It's so convenient and benefits people a lot".

poj 2513 Colored Sticks(欧拉回路 并查集 路径压缩 字典树)(困难)

Colored Sticks Time Limit: 5000MS   Memory Limit: 128000K Total Submissions: 32545   Accepted: 8585 Description You are given a bunch of wooden sticks. Each endpoint of each stick is colored with some color. Is it possible to align the sticks in a st

hdu 1251 字典树的应用

这道题看了大神的模板,直接用字典树提交的会爆内存,用stl 里的map有简单有快 #include <iostream> #include <map> #include <cstring> #include <string> using namespace std; int main() { int i, len; char str[10]; map<string, int> m; while( gets(str) ) { len = strle

hdu2072 字典树

这题印象深刻,我刚接触acm时,以为这题是水题(因为是中文,又短),一直没做出.现再想想也是.可能也是我以前字符串掌握不好: 这题其实也可以用stl里的map写.这里我用字典树写的.其实这题算简单题了吧. #include<stdio.h> #include<string.h> #include<stdlib.h> struct trie { trie *next[26]; int flag;//flag标记这里是否一个单词结束,也就是说到这里是否有一个单词: }; t

Trie(字典树)解析及其在编程竞赛中的典型应用举例

摘要: 本文主要讲解了Trie的基本思想和原理,实现了几种常见的Trie构造方法,着重讲解Trie在编程竞赛中的一些典型应用. 什么是Trie? 如何构建一个Trie? Trie在编程竞赛中的典型应用有些? 例题解析 什么是Trie? 术语取自retrieval中(检索,收回,挽回)的trie,读作"try",也叫做前缀树或者字典树,是一种有序的树形数据结构.我们常用字典树来保存字符串集合(但不仅限于字符串),如下图就是一个字典树. 它保存的字符集合是{to,te,tea,ted,te

『字典树 trie』

字典树 (trie) 字典树,又名\(trie\)树,是一种用于实现字符串快速检索的树形数据结构.核心思想为利用若干字符串的公共前缀来节约储存空间以及实现快速检索. \(trie\)树可以在\(O((n+m)*len)\)解决形如这样的字符串检索问题: 给定\(n\)个字符串,再给定\(m\)个询问,每次询问某个字符串在这\(n\)个字符串中出现了多少次 特点 \(trie\)树最显著的特点是,当它存储的若干个字符串有公共前缀时,它将不会重复存储. 与其他树形数据结构不同的是,\(trie\)树

hdu 1251 统计难题(字典树)

Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀). Input 输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串. 注意:本题只有一组测试数据,处理到文件结束. Output 对于每个提

51nod round3# 序列分解(折半枚举+字典树)

小刀和大刀是双胞胎兄弟.今天他们玩一个有意思的游戏. 大刀给小刀准备了一个长度为n的整数序列.小刀试着把这个序列分解成两个长度为n/2的子序列. 这两个子序列必须满足以下两个条件: 1.他们不能相互重叠. 2.他们要完全一样. 如果小刀可以分解成功,大刀会给小刀一些糖果. 然而这个问题对于小刀来说太难了.他想请你来帮忙. Input 第一行给出一个T,表示T组数据.(1<=T<=5) 接下来每一组数据,输入共2行. 第一行包含一个整数n (2<=n<=40且为偶数). 第二行给出n