POJ - 1002 487-3279 (Trie树)

题目:http://poj.org/problem?id=1002

题意:

n行号码,数字+大写字母+“-”,按照题意转化为纯数字的标准号码后,统计重复出现的号码,号码按顺序输出

分析:

输入后,转化成标准号码,可以用Trie树减少储存空间,最后深度优先搜索,把出现次数大于1的输出即可

代码:

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <string>
#include <math.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <map>

using namespace std;

#define MAX 1000+10
#define MIN -1e+10
#define INF 0x7f7f7f7f

int t, n, m;

struct Trie
{
	int id; // 出现次数
	Trie *child[11]; // 叶子节点
	Trie()
	{
		memset(child, 0, sizeof(child));
		id = 0;
	}
} root, tries[100000+10]; // 根节点,以及备用叶子节点
int t_num; // 叶子节点数目

int d[] = {2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 
		6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9}; // 字母映射数字

void insert(char str[]) // 插入号码
{
	Trie *x = &root;
	int p;
	for(int i = 0; str[i]; i++)
	{
		if(str[i] == '-') continue;

		if(str[i] >='0' && str[i] <='9')
			p = str[i] - '0';
		else if(str[i]>='A' && str[i] <='Z')
			p = d[str[i] - 'A'];

		if(x->child[p] == NULL)
			x->child[p] = &tries[t_num++];// 等价于 <span style="font-family: Arial, Helvetica, sans-serif;">x->child[p] = </span><span style="font-family: Arial, Helvetica, sans-serif;">new Trie;</span>

		x = x->child[p];
	}
	x->id ++;
}

int flag; // 是否有重复号码

void output(Trie *x, int num[], int len) // 递归输出重复号码
{
	if(len >= 7)
	{
		if(x->id == 1) return ;
		for(int i = 0; i<len; i++)
		{
			printf("%d", num[i]);
			if(i == 2) printf("-");
		}
		printf(" %d\n", x->id);
		flag = 1;
		return ;
	}
	for(int i =0; i<10; i++)
	{
		if(x->child[i] == NULL) continue;
		num[len] = i;
		output(x->child[i], num, len+1);
	}
}



int main()
{
	int i, j, k;
	freopen("a.txt", "r", stdin);

	char str[1000];
	while(~scanf("%d", &n))
	{
		cin.get();
		for(i = 0; i<n; i++)
		{
			gets(str);
			insert(str);
		}
		int num[100];
		flag = 0;
		output(&root, num, 0);
		if(!flag)
			printf("No duplicates.\n");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值