站点验证系统不做决定,请告诉我错误在哪里。
实际任务:
1002. 电话号码
时间限制:2.0 秒
内存限制:64 MB
在当今世界,您面临着大量的电话号码,这些电话号码随着时间的推移越来越长。你必须记住这些数字。一种容易记住的方法是将字母与每个数字匹配,如下图所示:
1 ij 2 abc 3 def
4 gh 5 kl 6 mn
7 prs 8 tuv 9 wxy
0 oqz
通过这种方式,可以为每个单词或单词组分配一个唯一的编号,以便记住单词而不是电话号码。显然,在用于记住电话号码的单词和该号码的所有者之间找到简单的关系具有特殊的魅力。因此,您下棋的朋友的电话号码 941837296 可以读作 WHITEPAWN(白兵),而您最喜欢的老师的电话号码 2855304 可以读作 BULLDOG(斗牛犬)。
编写一个程序,找到与给定电话号码和给定单词列表匹配的最短单词序列(具有最少单词)。对应关系如上图所示。
初始数据
输入由一组测试组成。每个测试的第一行包含您要匹配助记符的电话号码。该号码由不超过 100 位数字组成。第二行包含字典中的单词总数(最多 50,000 个)。剩下的每一行都包含一个单词,由不超过 50 个小写拉丁字母组成。总输入大小不超过 300 KB。最后一个输入行包含数字 -1。
结果
每行输出必须包含程序找到的最短单词序列。单词必须用单个空格分隔。如果输入没有解决方案,则相应的输出行应包含 text No solution.。如果有多个单词数相同的解决方案,您可以选择其中任何一个。
作者的输入和输出数据,例如:
7325189087
5
it
your
reality
real
our
4294967296
5
it
your
reality
real
our
-1
# Ожидаемый результат
reality our
No solution.
我的测试输入:
2272583262772
11
ba
ra
ku
k
ss
u
ma
da
m
a
ssa
-1
从逻辑上讲,答案应该是
ba ra ku da ma ssa
但由于某种原因,此解决方案不在可能的解决方案列表中。
如果你把它放在ma之后,da那么这个解决方案就找到了。
以下是从中做出最佳选择的解决方案列表:
['ba', 'ra', 'ku', 'da', 'm', 'a', 'ss', 'a']
['a', 'a', 'ra', 'ku', 'da', 'm', 'a', 'ss', 'a']
因此,最佳代码考虑:
ba ra ku da m a ss a
好吧,因此验证者不接受这个决定。
请告诉我错误在哪里
我的决定:
keyboard = {'1': 'ij', '2': 'abc', '3': 'def',
'4': 'gh', '5': 'kl', '6': 'mn',
'7': 'prs', '8': 'tuv', '9': 'wxy',
'0': 'oqz'}
while True:
phone_num = input()
solutions = []
if phone_num == '-1':
break
phone_len = len(phone_num)
words = [input() for _ in range(int(input()))]
collector = []
for word in words:
if len(word) > phone_len:
continue
solution = []
for i in range(len(word)):
if word[i] not in keyboard[phone_num[i]]:
break
else:
solution.append(word)
test_solution = []
while test_solution != solution:
test_solution = solution.copy()
raw_solution = ''.join(solution)
len_solution = len(raw_solution)
new_words = [item for item in words if len(item) <= phone_len - len_solution]
if new_words:
for item in new_words:
raw_solution = ''.join(solution)
len_solution = len(raw_solution)
test_string = raw_solution + item
len_test_string = len(test_string)
if len_test_string > phone_len:
continue
for s in range(len_solution, len_test_string):
if test_string[s] not in keyboard[phone_num[s]]:
break
else:
solution.append(item)
solutions.append(solution)
if solutions:
solutions.sort(key=lambda g: len(g))
print(*solutions[0])
else:
print('No solution.')
通用解法原理:
令 N 为电话号码的长度。
我们将字典表示为 M 个单词的列表。
所有字典单词都可以立即重写为数字序列。
然后我们创建一个维度为 N+1 x N+1 的方阵(我假设所有地方的索引都从 0 开始)。
矩阵的每个单元格 (i,j) = k 意味着我们有一个字典中编号为 k 的单词,它与电话数字的 i .. j-1 部分匹配。
用值 -1 填充其所有单元格。这将意味着我们没有这样的词。
然后,在所有单词的循环中,我们检查它们适合电话号码的哪一部分并填写矩阵。
然后,广度优先搜索在我们的矩阵中找到从 0 到 N 的路径。
如果找到路径,则路径的单元格值下的字典中的单词将是问题的解决方案,否则“无解决方案”。
矩阵填充时间 O(NxM)。广度优先搜索时间 O(NxN)。
不是最好的方法:
其余的你可能明白。
另一种解决方案。通过所有测试。