487-3279

日前看到了一个peking acm上看到了一个有意思的算法需求,如下:

问题原文:

Time Limit: 2000MS Memory Limit: 65536K

Description 
    Businesses like to have memorable telephone numbers. One way to make a telephone number memorable is to have it spell a memorable word or phrase. For example, you can call the University of Waterloo by dialing the memorable TUT-GLOP. Sometimes only part of the number is used to spell a word. When you get back to your hotel tonight you can order a pizza from Gino's by dialing 310-GINO. Another way to make a telephone number memorable is to group the digits in a memorable way. You could order your pizza from Pizza Hut by calling their ``three tens'' number 3-10-10-10. 
    The standard form of a telephone number is seven decimal digits with a hyphen between the third and fourth digits (e.g. 888-1200). The keypad of a phone supplies the mapping of letters to numbers, as follows: 
A, B, and C map to 2 
D, E, and F map to 3 
G, H, and I map to 4 
J, K, and L map to 5 
M, N, and O map to 6 
P, R, and S map to 7 
T, U, and V map to 8 
W, X, and Y map to 9 
There is no mapping for Q or Z. Hyphens are not dialed, and can be added and removed as necessary. The standard form of TUT-GLOP is 888-4567, the standard form of 310-GINO is 310-4466, and the standard form of 3-10-10-10 is 310-1010. 
Two telephone numbers are equivalent if they have the same standard form. (They dial the same number.) 

Your company is compiling a directory of telephone numbers from local businesses. As part of the quality control process you want to check that no two (or more) businesses in the directory have the same telephone number. 

Input 

The input will consist of one case. The first line of the input specifies the number of telephone numbers in the directory (up to 100,000) as a positive integer alone on the line. The remaining lines list the telephone numbers in the directory, with each number alone on a line. Each telephone number consists of a string composed of decimal digits, uppercase letters (excluding Q and Z) and hyphens. Exactly seven of the characters in the string will be digits or letters. 
Output
Generate a line of output for each telephone number that appears more than once in any form. The line should give the telephone number in standard form, followed by a space, followed by the number of times the telephone number appears in the directory. Arrange the output lines by telephone number in ascending lexicographical order. If there are no duplicates in the input print the line: 
No duplicates. 
Sample Input
12
4873279
ITS-EASY
888-4567
3-10-10-10
888-GLOP
TUT-GLOP
967-11-11
310-GINO
F101010
888-1200
-4-8-7-3-2-7-9-
487-3279
Sample Output
310-1010 2
487-3279 4

888-4567 3

问题翻译:

问题描述:
    商人们可以牢牢地记住电话号码,其中一个小技巧就是用一个单词或短语来记忆号码。例如,你在给Waterloo大学打电话的时候按键顺序为TUT-GLOP,所以你可以用TUT-GLOP来记忆Waterloo大学的号码。有些时候我们仅仅只需要用一部分单词来记忆号码,比如今晚回到酒店的时候你可以拨打310-GINO向Gino店预定一个披萨。另外一个记忆电话号码的技巧就是用一定的顺序来记忆号码。比如Pizza Hut的电话3-10-10-10你可以记成三个十。
    标准格式的电话号码是7位数,其中第三位和第四位数以-连接(比如888-1200)。电话的键盘数字和字母对应关系如下:
A,B,C  对应 2  
D,E,F  对应 3  
G,H,I  对应 4  
J,K,L   对应 5  
M,N,O 对应 6  
P,R,S  对应 7  
T,U,V  对应 8  
W,X,Y  对应 9  
    键盘上没有数字键对应到Q和Z字母。“-”符号不需要打出来,必要的时候可以被添加和删除。例如标准格式TUT-GLOP代表电话888-4567,310-GINO代表电话310-4466,3-10-10-10代表电话310-1010。

输入:
    输入只有一种情况,第一行为输入一个正整数代表输入电话号码的总条数(最大为100000),其余的行数列出电话薄里的电话号码,每一行为一个电话号码,由数字、大写字母(除Q,Z之外)和-组成。

输出:
    列出出现超过一次的电话号码。输出格式为标准格式电话号码 数目。输出以自然序列升序排序,若没有重复出现的电话号码,则输出:No duplicates.

举例:
输入:
12 
4873279 
ITS-EASY 
888-4567 
3-10-10-10 
888-GLOP 
TUT-GLOP 
967-11-11 
310-GINO 
F101010 
888-1200 
-4-8-7-3-2-7-9- 
487-3279 
输出:
310-1010 2 
487-3279 4 
888-4567 3

算法思路:

1、对录入字符串处理,计算录入字符串特征码即电话号码的数值。
2、利用二叉查找树按照自然排序来统计每个电话号码出现的次数。
3、结果输出。

c++实现如下(gcc (tdm-1) 4.7.1下编译通过):

#include <iostream>
#include <map>
#include <string>
using namespace std;
char dMap[] = {'2','2','2','3','3','3','4','4','4','5','5','5','6','6','6',
                '7','Q','7','7','8','8','8','9','9','9','Z'};

//获取标准电话格式
string getPhoneNum(string);
//字母数字映射
char getNum(char);
//replaceAll
string& replaceAll(string&, const string&, const string&);

int main(){
	map<string,int> phoneMap; 
	map<string,int>::iterator iter;
	int total;
	int cnt = 0;
	cin >> total;
	while(cnt++ < total){
		string phone;
		cin >> phone;
		string phoneNum = getPhoneNum(phone);
		//cout << phoneNum << endl;
		++phoneMap[phoneNum];
	}
	bool flag = false;
	map<string,int>::iterator end = phoneMap.end();

	for(iter = phoneMap.begin(); iter != end; ++iter){
		if(iter->second> 1){
			flag = true;
			cout<<iter->first<<" "<<iter->second<<endl;
		}
	}
	if(!flag){
		cout<<"No duplicates."<<endl;
	}
	return 0;
}

string& replaceAll(string& context, const string& from, const string& to){
	size_t lookHere = 0;
	size_t foundHere;

	while((foundHere = context.find(from, lookHere)) != string::npos) {
		context.replace(foundHere, from.size(), to);
		lookHere = foundHere + from.size();
	}
	return context;
}

string getPhoneNum(string phone){
	//去除首尾空格
	phone.erase(0,phone.find_first_not_of(" "));
    phone.erase(phone.find_last_not_of(" ") + 1);
	//替换掉'-'
	replaceAll(phone,"-","");
	//字符数字转换
	char phoneArr[phone.length() + 2];
	int tmp = 0;
	for (int i = 0; i < phone.length(); i++) {
		if(phone.at(i) == '-'){
			continue;
		}
		if(tmp == 3){
			phoneArr[tmp++] = '-';
		}
		phoneArr[tmp++] = getNum(phone.at(i));
	}
	phoneArr[phone.length()+1] = '\0';
	return string(phoneArr);
}
char getNum(char c){
	if(c >= 'A' && c <= 'Z'){
		int tmp = c - 'A';
		return dMap[tmp];
	}
	return c;
}

Java语言实现如下(在jdk1.5上通过测试):

package com.bigtiger.algorithm;

import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;

/**
 * 487-3279算法实现
 * @author bigtiger
 * @email [email protected]
 * @date 2013-8-18
 */
public class PhoneNumber {
	//数字字母映射表
	public final static char dMap[] = {'2','2','2','3','3','3','4','4','4','5','5',
                                            '5','6','6','6','7','Q','7','7','8','8','8',
                                            '9','9','9','Z'};
	
	public static void main(String[] args) throws NumberFormatException, IOException {
		//输入
		Scanner scanner = new Scanner(System.in);   
         int totalNum = Integer.parseInt(scanner.nextLine());
         int cnt = 0;
         Map<String, Integer> phoneMap = new TreeMap<String, Integer>();
         //录入号码并统计
         while (cnt++ < totalNum) { 
                 String phone = scanner.nextLine(); 
                 phone = phone.replaceAll("-", "").trim();
                 String phoneNum = getPhoneNum(phone);
                 Integer tcnt = phoneMap.get(phoneNum);
                 tcnt = tcnt == null ? 0 : tcnt;
                 phoneMap.put(phoneNum, tcnt + 1);
         } 
         //输出
         Set<Entry<String, Integer>> phoneMapEntries = phoneMap.entrySet();
         boolean flag = false;
         for (Entry<String, Integer> entry : phoneMapEntries) {
			if(entry.getValue() > 1){
				System.out.println(entry.getKey() + " " + entry.getValue());
				flag = true;
			}
		}
        if(!flag){
        	System.out.println("No duplicates.");
        } 
        }
	//获取标准电话格式
	private static String getPhoneNum(String phone){
		char[] phoneArr = new char[phone.length() + 1];
		for (int i = 0; i < phoneArr.length; i++) {
			if(i == 3){
				phoneArr[i++] = '-';
			}
			if(i < 3){
				phoneArr[i] = getNum(phone.charAt(i));
			}else {
				phoneArr[i] = getNum(phone.charAt(i-1));
			}
		}
		return new String(phoneArr);
	}
	//字母数字映射
	private static char getNum(char c){
		if(c >= 'A' && c <= 'Z'){
			return dMap[c-'A'];
		}
		return c;
	}
}

你可能感兴趣的:(算法,ACM,1002,487-3279)