poj_3283 trie树

题目大意

将一副牌进行编号,四种花色分别标记为‘C‘、‘D‘、‘H‘、‘S‘,数值标记为‘A‘、‘1‘、‘2‘、‘3‘、‘4‘、‘5‘、‘6‘、‘7‘、‘8‘、‘9‘、‘10‘、‘J‘、‘Q‘、‘K‘,则一张牌可以标记为 “数值+花色”,比如 7D, AH, 10S等。 
    给出N个牌的序列,每个序列视为一条链,每张牌视为链中的一个节点,为了方便存储,可以将具有相同后缀的链聚合在一起。求聚合之后的链中所有节点的个数。

题目分析

具有相同后缀的可以合并在一起,则等价于将每条链翻转之后,具有相同前缀的可以将前缀共享合并,这就是典型的trie结构。因此,需要将牌进行hash之后,获得索引,然后插入trie树中。

  其中,翻转操作可以通过stack的push/pop来实现。
    为了求得总共的节点的数目,可以使用静态数组方式而不是指针方式来存储trie树。

实现(c++)

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stack>
using namespace std;
#define MAX_CHILD_NUM 53
char gSuit[4] = { ‘C‘, ‘D‘, ‘H‘, ‘S‘ };
char gValue[4] = { ‘A‘, ‘J‘, ‘Q‘, ‘K‘ };
int gValueHash[4] = { 0, 10, 11, 12 };
struct Card{
	int suit;
	int value;
};
void CardHash(char* card, Card& car){
	char suit, value;
	if (strlen(card) == 3){
		suit = card[2];
		car.value = 9;
	}
	else{
		suit = card[1];
		value = card[0];

		if (value >= ‘2‘ && value <= ‘9‘){
			car.value = value - ‘0‘ - 1;
		}
		else{
			for (int i = 0; i < 4; i++){
				if (gValue[i] == value){
					car.value = gValueHash[i];
					break;
				}
			}
		}
	}
	int i;
	for (i = 0; i < 4; i++){
		if (gSuit[i] == suit){
			break;
		}
	}
	car.suit = i;
}

struct TrieNode{
	int count;
	int childs[MAX_CHILD_NUM];
	TrieNode(){
		count = 0;
		memset(childs, 0, sizeof(childs));
	}
};

TrieNode gNodes[100000];
int gIndex;

void Insert(int root, stack<Card>& card_stack){
	int node = root;
	Card card;
	while (! card_stack.empty()){
		card = card_stack.top();
		card_stack.pop();

		int index = 13 * card.suit + card.value;
		if (gNodes[node].childs[index] == 0){
			gNodes[node].childs[index] = gIndex++;
		}
		node = gNodes[node].childs[index];

	}
	gNodes[node].count++;
}

int main(){
	int n, m;
	char card[4];
	stack<Card> card_stack;
	int suit, value;
	Card car;
	while (scanf("%d", &n) != EOF){
		if (n == 0){
			break;
		}
		memset(gNodes, 0, sizeof(gNodes));
		gIndex = 2;
		while (n--){
			scanf("%d", &m);
			getchar();
			for (int i = 0; i < m; i++){
				for (int k = 0; k < 3; k++){
					scanf("%c", card + k);
				}
				if (*(card + 1) == ‘0‘){
					*(card + 3) = 0;
					getchar();
				}
				else{
					*(card + 2) = 0;
				}
				CardHash(card, car);
				//printf("card = %s\n", card);
				card_stack.push(car);
			}
			Insert(1, card_stack);
		}
		printf("%d\n", gIndex - 2);
	}
	return 0;
}
时间: 2024-10-09 21:22:22

poj_3283 trie树的相关文章

poj3630 Phone List (trie树模板题)

Phone List Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 26328   Accepted: 7938 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 catalogu

跳跃表,字典树(单词查找树,Trie树),后缀树,KMP算法,AC 自动机相关算法原理详细汇总

第一部分:跳跃表 本文将总结一种数据结构:跳跃表.前半部分跳跃表性质和操作的介绍直接摘自<让算法的效率跳起来--浅谈"跳跃表"的相关操作及其应用>上海市华东师范大学第二附属中学 魏冉.之后将附上跳跃表的源代码,以及本人对其的了解.难免有错误之处,希望指正,共同进步.谢谢. 跳跃表(Skip List)是1987年才诞生的一种崭新的数据结构,它在进行查找.插入.删除等操作时的期望时间复杂度均为O(logn),有着近乎替代平衡树的本领.而且最重要的一点,就是它的编程复杂度较同类

Trie树学习2

数组实现的Trie树 字符容量有限,可以使用链表实现更为大容量的Trie #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <vector> #include <map> #include <set> #include <algorithm> #include <cstdlib> #

trie树(字典树)

1. trie树,又名字典树,顾名思义,它是可以用来作字符串查找的数据结构,它的查找效率比散列表还要高. trie树的建树: 比如有字符串"ab" ,"adb","adc"   可以建立字典树如图: 树的根节点head不存储信息,它有26个next指针,分别对应着字符a,b,c等.插入字符串ab时,next['a'-'a']即next[0]为空,这是申请一个结点放在next[0]的位置,插入字符串db时,next['d'-'a']即next[3]

Trie树

Trie树,即字典树或单词查找树,主要用于大量字符串的检索.去重.排序等操作. 主要原理就是利用字符串的公共前缀建立一棵多叉树,牺牲空间换取时间. 1 //Trie树 2 #include <iostream> 3 #include <string> 4 using std::cin; 5 using std::cout; 6 using std::endl; 7 using std::string; 8 9 const int SIZE = 26; 10 const char B

bzoj4103异或运算 可持久化trie树

要去清华冬令营了,没找到2016年的题,就先坐一坐15年的. 因为n很小,就按照b串建可持久化trie树,a串暴力枚举. 其他的直接看代码. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; inline int read() { int x=0,f=1,ch=getchar(); while(ch<'0'||ch

hihoCoder 1014 Trie树

#1014 : Trie树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一本词典,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能对于每一个我给出的字符串,都在这个词典里面找到以这个字符串开头的所有单词呢?” 身经百战的小Ho答道:“怎么会不能呢!你每给我一个字符串,我就依次遍历词典里的所有单词,检查你给我的字

HDU 1251 Trie树模板题

1.HDU 1251 统计难题  Trie树模板题,或者map 2.总结:用C++过了,G++就爆内存.. 题意:查找给定前缀的单词数量. #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #define max(a,b) a>b?a:b #define F(i,a,b

hiho一下 第二周&amp;第四周:从Trie树到Trie图

hihocoder #1014 题目地址:http://hihocoder.com/problemset/problem/1014 hihocoder #1036 题目地址: http://hihocoder.com/problemset/problem/1036 trie图其实就是trie树+KMP #1014trie树 #include<stdio.h> #include <algorithm> #include <cstring> #include <str