1. 问题描述:
一个电话销售员正在整理他的电话簿。电话簿中记录了他的全部客户的电话号码。一个客户可能有不止一个电话号码。不同客户可能拥有完全相同的电话号码。电话簿中一共包含 n 条记录。每条记录都是首先包含一个字符串,表示客户的姓名,然后包含一个整数,表示本条记录包含的电话号码数量,最后是本条记录所包含的电话号码。不同客户的姓名两两不同,所以如果两条记录包含的客户姓名相同,那么我们认为这都是记录的同一人的电话信息。同一记录中可能包含相同的电话号码,不同记录中也可能包含相同的电话号码。在进行整理时,应遵守如下原则:
如果一个客户拥有多条记录,则需要将这些记录进行合并,每人只保留一条记录,去记录他的全部有效号码。
如果一个客户记录的多个电话号码完全相同,则只保留一个作为有效号码,其余的全部视为无效号码。
如果一个客户记录的两个不同电话号码 a 和 b 满足 a 是 b 的后缀,则号码 a 视为无效号码。
请输出整理后的电话记录。
输入格式
第一行包含整数 n,表示记录数量。接下来 n 行,每行描述一条记录,首先包含一个长度不超过 10 的由小写字母构成的非空字符串,表示客户姓名,然后包含一个不超过 10 的正整数,表示本条记录包含的号码数量,最后包含本条记录的所有号码,每个号码都是长度不超过 10 的由数字构成的非空字符串,可能包含前导 0。
输出格式
首先输出一个整数 m,表示完成整理后的记录数量。接下来 m 行,每行输出一条记录信息,格式要求与输入一致。同一行的数据之间用单个空格隔开。记录的先后顺序随意,一条记录中的号码顺序随意。
数据范围
前三个测试点满足 1 ≤ n ≤ 4。
所有测试点满足 1 ≤ n ≤ 20。
输入样例1:
2
i 1 00123
m 1 00123
输出样例1:
2
m 1 00123
i 1 00123
输入样例2:
3
l 2 612 12
p 1 12
k 1 612
输出样例2:
3
k 1 612
p 1 12
l 1 612
输入样例3:
4
i 3 123 123 456
i 2 456 456
i 8 789 3 23 6 56 9 89 2
d 2 23 789
输出样例3:
2
d 2 23 789
i 4 789 123 2 456
来源: https://www.acwing.com/problem/content/description/4211/
2. 思路分析:
分析题目可以知道我们需要合并相同姓名的所有手机号码,并且这些手机号码是有效的,所以需要建立姓名与手机号码之间的关系,这里可以使用哈希表来建立这种对应关系,并且我们需要去除掉一个字符串是另外一个字符串的后缀的情况,这里可以使用的一个技巧是在存储手机号码的时候存储后缀,这样对字符串排序之后如果一个字符串是另外一个字符串的前缀,那么它肯定是排在前缀的前面,这样就可以判断出一个字符串是否是另外一个字符串的后缀了,所以我们判断当前字符串是否是下一个字符串的前缀即可,如果不是说明当前字符串是合法的需要记录下来,最终对合法的手机号码再反转一下输出即可。
3. 代码如下:
class Solution:
# 使用哈希表记录即可
def process(self):
n = int(input())
# 字典的值为set, 这样去除掉重复掉重复元素
mp = dict()
for i in range(n):
s = input().split()
n = int(s[1])
for j in range(n):
if s[0] not in mp:
# 存储前缀后面在比较的时候会方便一点, [::-1]表示翻转一下字符串
mp[s[0]] = {s[j + 2][::-1]}
else:
mp[s[0]].add(s[j + 2][::-1])
print(len(mp))
for k, v in mp.items():
t = list(v)
t.sort()
res = list()
for i in range(len(t)):
if i + 1 < len(t):
# 排序之后如果一个字符串是另外一个字符串的前缀那么肯定是相邻的
if t[i + 1].startswith(t[i]): continue
res.append(t[i])
print(k, len(res), end=" ")
for x in res:
print(x[::-1], end=" ")
print()
if __name__ == '__main__':
Solution().process()