码迷,mamicode.com
首页 > 其他好文 > 详细

poj_3630 trie树

时间:2015-09-17 00:50:24      阅读:272      评论:0      收藏:0      [点我收藏+]

标签:

题目大意

    给定一系列电话号码,查看他们之间是否有i,j满足,号码i是号码j的前缀子串。

题目分析

    典型的trie树结构。直接使用trie树即可。但是需要注意,若使用指针形式的trie树,则在大数据量下new/delete会很耗时,因此使用静态数组来存储trie树结构。使用静态数组代替指针在oj中常用于节省时间!

实现(c++)

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#define MAX_CHILD_NUM 10
#define MAX_NODE_NUM 1 << 16
struct TrieNode{
	int count;
	int childs[MAX_CHILD_NUM];
	TrieNode(){
		count = 0;
		memset(childs, 0, sizeof(childs));
	}
};

TrieNode gNodes[MAX_NODE_NUM];	//静态数组方式存储
int gCount;
bool Insert(int root, char* str){
	int node = root;
	char* p = str;
	while (*p != ‘\0‘){
		int index = *p - ‘0‘;
		if (gNodes[node].childs[index] == 0){
			gNodes[node].childs[index] = gCount++;
		}
		node = gNodes[node].childs[index];
		if (gNodes[node].count == 2){		//若为某个号码的结尾,则说明出现了前缀子串。
			return false;
		}
		if (*(p + 1) == ‘\0‘&&gNodes[node].count == 1){		//特殊情况,画图分析很容易看出
			return false;
		}
		gNodes[node].count = 1;		//为1 表示该节点是某个号码内部的点
		p++;
	}
	if (gNodes[node].count == 2){		//为2说明该点是某个号码结尾的点
		return false;
	}
	gNodes[node].count = 2;
	return true;
}


int main(){
	int cas;
	char number[20];
	scanf("%d", &cas);
	for (int i = 0; i < cas; i++){
		memset(gNodes, 0, sizeof(gNodes));
		gCount = 2;

		int n;
		scanf("%d", &n);
		getchar();
		bool flag = true;
		for (int k = 0; k < n; k++){
			scanf("%s", number);
			if (flag)
				flag = Insert(1, number);
		}
		if (!flag)
			printf("NO\n");
		else
			printf("YES\n");
	}
	return 0;
}

 

poj_3630 trie树

标签:

原文地址:http://www.cnblogs.com/gtarcoder/p/4814987.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!