~欢迎你!第 AmazingCounters.com 位造访者

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这个很卡时间,数据再强一点也许就卡了。
 
然后再HDU上提交,HDU把内存卡30M了,所以普通的字典树内存可能不够,就改进写成了树状数组(静态字典树),内存就被压缩到了6.7M,也能过了;

字典树法:
#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
**********************************************************************/

  






posted @ 2017-04-23 16:25  ~HDMaxfun  阅读(187)  评论(0编辑  收藏  举报