POJ1002 487-3279

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

题目大意:

  (背景)企业喜欢容易被人记住的电话号码。使一个电话号码容易被记住的一种方法是让它“拼”(spell)出来是一个好记的单词或短语(与手机键盘上的字母联系起来)。比如,你可以拨打好记的TUT-GLOP打电话给滑铁卢大学。有时,也可以只让号码的一部分拼成一个单词。当你晚上回到宾馆,你可以拨打310-GINO从Gino's订一份披萨。另一种让号码好记的方式是将号码分成好记的组。比如,你可以打“3个10”电话3-10-10-10订必胜客的pizza。

  电话号码的标准形式是一个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.

  如果两个号码的标准形式相同,那么我们认为这两个号码是相同的。

  你的公司在为本地商人们编辑一个电话号码薄,作为质量控制的一部分,你希望检查号码薄中是否存在相同的号码。

  输入:测试数据仅含一个样例。第一行为一个正整数,为号码个数(最大到100,000)。接下来的每行为号码薄中的一个号码。号码可能含有数字、字母(大写,不含A和Z)和短横线。数字和字母的个数为7.

  输出:每行输出一个出现多次的电话号码的标准形式,空格后输出该号码出现了多少次。按号码的升序输出。若没有重复号码输出一行文字:“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

测试数据:http://acm.student.cs.uwaterloo.ca/~acm00/regionals/

     Contest Data -> Real -> Testing data and solutions -> E

解题关键:

  1.建立字母->数字之间的映射关系

  2.按映射关系进行映射,将所有号码转换为标准形式

  3.将所得的标准形式进行排序和统计,输出统计结果

最开始用Java的HashMap做,发现内存和时间都大得惊人。所以这是第一次,可能也是最后一次用Java刷题了吧。

 1 //////////////////////////////////////////////////////////////
 2 //         POJ1002 487-3279
 3 //        Memory: 19176K        Time: 5422MS
 4 //        Language: Java        Result: Accepted
 5 /////////////////////////////////////////////////////////////
 6 
 7 import java.util.HashMap;
 8 import java.util.Map;
 9 import java.util.Map.Entry;
10 import java.util.Scanner;
11 import java.util.TreeMap;
12 
13 public class Main {
14     private Map<Character, Integer> mapper = new HashMap<Character, Integer>();
15 
16     public void initial() {
17         mapper.put('A', 2);
18         mapper.put('B', 2);
19         mapper.put('C', 2);
20         mapper.put('D', 3);
21         mapper.put('E', 3);
22         mapper.put('F', 3);
23         mapper.put('G', 4);
24         mapper.put('H', 4);
25         mapper.put('I', 4);
26         mapper.put('J', 5);
27         mapper.put('K', 5);
28         mapper.put('L', 5);
29         mapper.put('M', 6);
30         mapper.put('N', 6);
31         mapper.put('O', 6);
32         mapper.put('P', 7);
33         mapper.put('R', 7);
34         mapper.put('S', 7);
35         mapper.put('T', 8);
36         mapper.put('U', 8);
37         mapper.put('V', 8);
38         mapper.put('W', 9);
39         mapper.put('X', 9);
40         mapper.put('Y', 9);
41     }
42     
43     public Map<Character, Integer> getMapper() {
44         return mapper;
45     }
46 
47     public static void main(String[] args){
48         Main test = new Main();
49         test.initial();
50         
51         Scanner scanner = new Scanner(System.in);
52         Map<String, Integer> hMap = new TreeMap<String, Integer>();
53         int lines = Integer.parseInt(scanner.nextLine().trim());
54         if (lines == 1) {
55             System.out.println("No duplicates.");
56         }
57         String[] tels = new String[lines];
58         for (int i = 0; i < lines; i++) {
59                 tels[i] = scanner.nextLine();
60         }
61         for (String line : tels) {
62             StringBuffer sb = new StringBuffer();
63             for (int i = 0; i < line.length(); ++i) {
64                 char ch = line.charAt(i);
65                 if (Character.isLetter(ch)) {
66                     sb.append(test.getMapper().get(ch));
67                 } else if (Character.isDigit(ch)) {
68                     sb.append(ch);
69                 }
70             }
71             sb.insert(3, '-');
72             String key = sb.toString();
73             if (hMap.containsKey(key)) {
74                 hMap.put(key, hMap.get(key) + 1);
75             } else {
76                 hMap.put(key, 1);
77             }
78         }
79         int tag = 0;
80         for (Entry<String, Integer> entry : hMap.entrySet()) {
81             String key = entry.getKey();
82             int value = entry.getValue();
83             if (value > 1){
84                 System.out.println(key + " " + value);
85                 tag++;
86             }
87         }
88         if (tag == 0) {
89             System.out.println("No duplicates.");
90         }    
91         scanner.close();
92         return;    
93     }
94 }
View Java Code

然后,发现题目给出的映射关系中,每三个字母映射到一个数字,可以用取模运算。用C++重写了一次。

 1 //////////////////////////////////////////////////////////////////////////
 2 //        POJ1002 487-3279
 3 //        Memory: 3040K        Time: 1094MS
 4 //        Language: C++        Result: Accepted
 5 //////////////////////////////////////////////////////////////////////////
 6 
 7 #include <iostream>
 8 #include <string>
 9 #include <algorithm>
10 
11 using namespace std;
12 
13 void output(string str, int cnt) {
14     for (int i = 0; i < 3; ++i) {
15         cout << str[i];
16     }
17     cout << '-';
18     for (int i = 3; i < 7; ++i) {
19         cout << str[i];
20     }
21     cout << " " << cnt;
22     cout << endl;
23 } 
24 
25 int main(void) {
26     int n;
27     cin >> n;
28     int no = n;
29     string * ans = new string[n];
30     while(no--) {
31         string buff;
32         string stdForm;
33         cin >> buff;
34         //转换为标准形式
35         for (string::iterator it = buff.begin(); it != buff.end(); ++it) {
36             if (isdigit(*it)) {
37                 stdForm += *it;
38             } else if ((*it) >= 'A' && (*it) < 'Q') {
39                 stdForm += (char) (((*it) - 'A') / 3 + '2');
40             } else if ((*it) > 'Q' && (*it) < 'Z') {
41                 stdForm += (char) (((*it) - 'A' - 1) / 3 + '2');
42             }
43         } 
44         ans[no] = stdForm;
45     }
46     sort(ans, ans + n);
47     bool flag = false;
48     int cnt = 1;
49     //统计
50     for (int i = 0; i < n; ++i) {
51         if (i + 1 == n) {
52             if (cnt != 1) {
53                 output(ans[i], cnt);
54             }
55         } else if (ans[i + 1] == ans[i]) {
56             ++cnt;
57             flag = true;
58         } else {
59             if (cnt != 1) {
60                 output(ans[i], cnt);
61                 cnt = 1;
62             }
63         }
64     }
65     if (flag == false) {
66         cout << "No duplicates." << endl;
67     }
68     system("pause");
69     return 0;
70 }
View Code

发现还是很慢,看了Discuss里别人的代码,把标准形式的保存形式由string改为int,把所有的cin、cout改为scanf和printf,果然快了不少。

 1 //////////////////////////////////////////////////////////////////////////
 2 //        POJ1002 487-3279
 3 //        Memory: 596K        Time: 329MS
 4 //        Language: C++        Result: Accepted
 5 //////////////////////////////////////////////////////////////////////////
 6 
 7 #include <cstdio>
 8 #include <algorithm>
 9 
10 using namespace std;
11 
12 int main(void) {
13     int n;
14     scanf("%d", &n);
15     int no = n;
16     int * ans = new int[n];
17     while(no--) {
18         char buff[50];
19         char c;
20         int stdForm = 0;
21         int i = 0;
22         scanf("%s", buff);
23         //转换为标准形式
24         while ((c = buff[i++]) != '\0') {
25             if (c >= '0' && c <= '9') {
26                 stdForm = stdForm * 10 + c - '0';
27             } else if (c >= 'A' && c < 'Q') {
28                 stdForm = stdForm * 10 + (c - 'A') / 3 + 2;
29             } else if (c > 'Q' && c < 'Z') {
30                 stdForm = stdForm * 10 + (c - 'A' - 1) / 3 + 2;
31             }
32         }
33         ans[no] = stdForm;
34     }
35     sort(ans, ans + n);
36     bool flag = false;
37     int cnt = 1;
38     //统计&输出
39     for (int i = 0; i < n; ++i) {
40         if (i + 1 == n) {
41             if (cnt != 1) {
42                 printf("%03d-%04d %d\n", ans[i] / 10000, ans[i] % 10000, cnt);
43             }
44         } else if (ans[i + 1] == ans[i]) {
45             ++cnt;
46             flag = true;
47         } else {
48             if (cnt != 1) {
49                 printf("%03d-%04d %d\n", ans[i] / 10000, ans[i] % 10000, cnt);
50                 cnt = 1;
51             }
52         }
53     }
54     if (flag == false) {
55         printf("No duplicates.\n");
56     }
57     system("pause");
58     return 0;
59 }
View Code

我大概也就能优化成这样了,有大牛的实现30ms内完成,只能膜拜。

posted @ 2013-07-30 16:41  小菜刷题史  阅读(395)  评论(0编辑  收藏  举报