BIT小学期-电话号码问题

Output

输出包括两个部分,第一个部分是错误的电话号码,对于这些号码应当按照输入的顺序以原始的形式输出。在输出错误电话号码前输出Error:,随后输出这些号码,如果没有错误的电话号码,则输出Not found.

第二部分是重复的正确的电话号码,对每一个在电话簿中以任何形式出现一次以上的电话号码,生成一行输出。这一行应以标准形式给出电话号码,其后跟随一个空格,空格后跟随电话号码在电话簿中出现的次数。所有重复的电话号码输出行应以号码的升序排列(小号码在前)。在输出重复电话号码前输出Duplication,随后按照上述格式输出号码,如果在输入中没有重复的电话号码,则输出:Not found.

Note

你所编写的程序以后可能会在一种特殊的嵌入式设备上运行,为了降低成本,这种设备使用的 CPU 不是很快、可用的 RAM 为 288K(跟 GBA 一样)且它没有磁盘设备因此不能使用文件作为数据的临时存储。

Hint

请参考《编程珠玑》第一部分,若程序不能在规定的内存中运行,则不得分

测试输入期待的输出时间限制内存限制额外进程
测试用例 1以文本方式显示
  1. 4873279↵
  2. ITS-EASY↵
  3. 666-4567↵
  4. 3-10-10-10↵
  5. 666-GLOP↵
  6. MON-GLOP↵
  7. 367-11-11↵
  8. 310-GINO↵
  9. F101010↵
  10. 666-1200↵
  11. -4-8-7-3-2-7-9↵
  12. 487-3279↵
以文本方式显示
  1. Error:↵
  2. 4873279↵
  3. ITS-EASY↵
  4. -4-8-7-3-2-7-9↵
  5. 487-3279↵
  6. Duplication:↵
  7. 310-1010 2↵
  8. 666-4567 3↵
1秒512KB0
测试用例 2以文本方式显示
  1. 3456789↵
以文本方式显示
  1. Error:↵
  2. Not found.↵
  3. Duplication:↵
  4. Not found.↵
1秒512KB0

电话号码合法性的判断和输出就不讲了,只要在到判断到非法时直接输出即可。

这道题由于这道题的内存卡得很死,所以在记录号码是否记录过时 用bitset,每 一个位 (0或1)记录一个号码的状态。又因为合法的号码必须是3或6,所以最多2000000个 bit 就能记录下所有合法号码的状态。0代表号码未访问过,1代表号码已经访问。

对于已经访问过的号码,就存入哈希表中,如果已经存入哈希表中了,那就将出现次数增加

这样存储的话:【 (2000000/8) + (4+2)*1505 + 4*21】/1024 = 253KB   再加上其他定义的一些int变量,这个空间也是完全够用的。

几个注意点:

1.用char [ ] 来获取输入字符串,而不是string,因为string会占用额外的空间

2.将字母与数字映射时,最好不要用map,可以写个switch函数来判断,虽然慢点,但是不占空间

3.在判断完是否合法后,不合法直接输出,合法的话,转换成int类型,因为继续用字符串保存的话占用空间更大。

4.对于排序:直接用sort,写一个cmp函数就行

#include <bits/stdc++.h>
using namespace std;

int dc = 0;
bitset<1000000> arr[2];

struct mymap {
    int num;
    short c;
} d[1505];

bool cmp(mymap a, mymap b) {
    return a.num < b.num;
}

int getNumber(char ch) {
    switch (ch) {
        case 'A': case 'B': case 'C':
            return 2;
        case 'D': case 'E': case 'F':
            return 3;
        case 'G': case 'H': case 'I':
            return 4;
        case 'J': case 'K': case 'L':
            return 5;
        case 'M': case 'N': case 'O':
            return 6;
        case 'P': case 'R': case 'S':
            return 7;
        case 'T': case 'U': case 'V':
            return 8;
        case 'W': case 'X': case 'Y':
            return 9;
        default:
            return -1; // 返回 -1 处理无效字符
    }
}

void insert(int a) {
    int pos = a % 1503;
    while(1){
        if (d[pos].num == 0 && d[pos].c == 0) {
            d[pos].num = a;
            d[pos].c = 2;
            dc++;
            return;
        } else if (d[pos].num == a) {
            d[pos].c++;
            return;
        } else {
            pos = (pos + 1) % 1503;
        }
    }
}

int main() {
    char temp[21];
    int num, len, begin, c, w;
    int i, flag = 0;
    printf("Error:\n");
    while (cin.getline(temp, 21)) {
        num = 0;
        len = strlen(temp);
        begin = 0;
        c = w = 0;
        if(temp[0]=='\0'){
            break;
        }
        // 去除前面的 '-'
        while (temp[begin] == '-') {
            begin++;
        }

        if (begin == len) {
            flag = 1;
            cout << temp << endl;
            continue;
        }

        if (temp[begin] == '3' || getNumber(temp[begin]) == 3) {
            w = 0;
        } else if (temp[begin] == '6' || getNumber(temp[begin]) == 6) {
            w = 1;
        }

        if (temp[begin] == '3' || getNumber(temp[begin]) == 3 ||
            temp[begin] == '6' || getNumber(temp[begin]) == 6) {
            for (i = begin + 1; i < len; i++) {
                if (temp[i] == '-') {
                    continue;
                } else {
                    c++;
                    if (temp[i] >= '0' && temp[i] <= '9') {
                        num = num * 10 + (temp[i] - '0');
                    } else {
                        int number = getNumber(temp[i]);
                        if (number >= 0 && number <= 9) {
                            num = num * 10 + number;
                        } else {
                            flag = 1;
                            cout << temp << endl;
                            break;
                        }
                    }
                }
            }
            if (i == len && c != 6) {
                flag = 1;
                cout << temp << endl;
                continue;
            }
            if (i == len) {
                if (arr[w].test(num)) {
                    insert((w + 1) * 3000000 + num);
                } else {
                    arr[w].set(num);
                }
            }
        } else {
            flag = 1;
            cout << temp << endl;
        }
    }

    if (flag == 0) {
        printf("Not found.\n");
    }
    printf("\nDuplication:\n");
    sort(d, d + 1505, cmp);
    for (int k = 1505 - dc; k < 1505; ++k) {
        printf("%03d-%04d %d\n", d[k].num / 10000, d[k].num % 10000, d[k].c);
    }
    if (dc == 0) {
        printf("Not found.\n");
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值