|
问题:书加密法是一种发送者和接收者使用相同的文本对信息进行编码和解码的方法。发送者对信息进行编码时,使用 "s.w.c" 格式将要发送的信息中的每个字母数字字符替换为该字符在文本中的位置。"s.w.c" 格式代表文本中句子的编号(s),句子中单词的编号(w),单词中字符的编号(c),所有编号均从 1 开始。接收者通过查找每个"s.w.c" 字符串在文本中指定的字符来对编码信息进行解码。在此程序中,将给定文本以及需解码的编码信息。该文本有以下限制条件:每个单词只包含字母数字字符每个单词之间均用一个空格或任意非字母数字字符(一个或多个)分隔句子以句号、问号或感叹号结束,且句子之间严格用两个空格分隔文本中可以出现任意键盘字符编码信息将包含多个 "s.w.c" 字符串,每个字符串之间用一个空格分隔。通过在文本中查找每一个字符来创建解码信息。如果 "s.w.c" 字符串并不指向文本中的某个字母数字字符,则在解码信息中使用一个空格代替。
样例:
输入:
ACSL, or the American Computer Science League, is an international computer science competition among more than 300 schools. Originally founded in 1978 as the Rhode Island Computer Science League, it then became the New England Computer Science League. With countrywide and worldwide participants, it became the American Computer Science League. It has been in continuous existence since 1978. Each yearly competition consists of 4 regular-season contests. All students at each school may compete but the team score is the sum of the best 3 or 5 top scores. Each contest consists of two parts: a written section (called shorts) and a programming section. Written topics tested include what does this program do, digital electronics, Boolean algebra, computer numbering systems, recursive functions, data structures (primarily dealing with heaps, binary search trees, stacks, and queues), Lisp programming, regular expressions and Finite State Automata, bit string flicking, graph theory, assembly language programming, and prefix/infix/postfix notation.
3.5.1 8.21.9 1.10.8 2.7.2 7.15.6 5.4.3 4.10.3 6.18.1
输出:
python 3
解释说明:第一个编码字符串 "3.5.1" 告诉你要先查找到第 3 句话,接着找到这句话的第 5 个单词"participants",最后找到这个单词里的第 1 个字符,即小写字母 'p'。所有其它字符的查找方式都与此类似。因为第 4 句话中只有 8 个单词,所以字符串 "4.10.3" 用一个空格代替。
解析:
单次查找并不困难,因为句子之间的分隔明确为句号、问号或感叹号,而其他非字母数字字符以及空格都是单词之间的分隔标志,遍历文本的同时进行计数即可,但此时我们可以发现,每次进行遍历查找的计数工作实际上是重复的,我们完全可以做到用二位列表在第一次遍历时提前存储每句句子和单词的内容,第一层下标表示句子的序号,第二层下标表示局内单词的序号,单词以字符串形式存储,可以直接获取长度和指定位置的字符,查找时下标超出单词长度则输出空格,这样我们就通过预处理大大优化了时间复杂度,考虑到单纯的查找较为简单,很可能数据规模较大,不进行预处理会导致超时
代码:
# 测试数据
txt = '''ACSL, or the American Computer Science League, is an international computer science competition among more than 300 schools. Originally founded in 1978 as the Rhode Island Computer Science League, it then became the New England Computer Science League. With countrywide and worldwide participants, it became the American Computer Science League. It has been in continuous existence since 1978. Each yearly competition consists of 4 regular-season contests. All students at each school may compete but the team score is the sum of the best 3 or 5 top scores. Each contest consists of two parts: a written section (called shorts) and a programming section. Written topics tested include what does this program do, digital electronics, Boolean algebra, computer numbering systems, recursive functions, data structures (primarily dealing with heaps, binary search trees, stacks, and queues), Lisp programming, regular expressions and Finite State Automata, bit string flicking, graph theory, assembly language programming, and prefix/infix/postfix notation. '''
location = '3.5.1 8.21.9 1.10.8 2.7.2 7.15.6 5.4.3 4.10.3 6.18.1'
# txt = input()
# location = input()
#---------建立数据list--------------
lList = location.split(' ')
for i in range(len(lList)):
lList = lList.split('.') # 生成字母位置 双层list
for i in range(len(lList)):
for ii in range(len(lList)):
lList[ii] = int(lList[ii]) # 将每个str转化为int
aList = ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c',
'v', 'b', 'n', 'm', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K',
'L', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
tList = txt.split(' ') # 第一步处理数据,整理出句子
for i in range(len(tList)):
tList = tList.split(' ') # 第二步处理数据,整理出词汇
#------------第一次处理符号(如果符号在词的最前、最后),删除第一层符号---------------
for x in range(len(tList)):
for y in range(len(tList[x])):
try: # 在删除符号后可能会出问题,因此用try
for n in range(len(tList[x][y])): # 在每个词语中处理掉符号
flag = 0
for i in range(len(aList)): # 看每个字母是不是符号 (flag = 0: 符号, flag = 1: 字母)
if tList[x][y][n] == aList: #如果字母和字母list中重合
flag = 1
else:
continue
if flag == 1:
continue
else: # 如果字母是符号(没有在字母list中出现):
if n == 0: # 如果符号是在词语最前面
tList[x][y] = tList[x][y][1:] #删除符号
elif n == len(tList[x][y]) - 1: #如果符号在词语后面
tList[x][y] = tList[x][y][:-1] #删除符号
except IndexError:
continue
#------------第二次处理符号(处理符号在词的中间,以及词语开头、结尾有两个连续符号的情况!!)
for x in range(len(tList)):
for y in range(len(tList[x])):
for n in range(len(tList[x][y])):
flag = 0
for i in range(len(aList)): # 和上面一样
try:
if tList[x][y][n] == aList:
flag = 1
else:
continue
except IndexError:
continue
if flag == 1:
continue
else:
if n == 0:
tList[x][y] = tList[x][y][1:]
elif n == len(tList[x][y]) - 1:
tList[x][y] = tList[x][y][:-1]
else: # 如果符号在词语中间
for g in range(len(tList[x][y])): # 找到符号在词语中的位置
rflag = 0 # 这个字母是不是符号 (flag = 0: 符号, flag = 1: 字母)
for f in range(len(aList)):
try: #避免把符号从list删除后list不够长导致的error
if tList[x][y][g] == aList[f]: #把字母和字母list中一一核对,如果没有核对成功则是符号
rflag = 1
except IndexError:
continue
if rflag == 0: #如果这个字母是符号
try: #避免list不够长的错误
arList = tList[x][y].split(tList[x][y][g]) #把当前word在前面按照查出的符号split开来
except IndexError:
continue
tList[x].pop(y) #删除原来有符号的词
for i in range(len(arList)):
tList[x].insert(y + i, arList) #按照顺序把整理出来的词语一一插入list
fin = ''
for i in range(len(lList)):
sentence = lList[0] - 1
word = lList[1] - 1
letter = lList[2] - 1
try:
fin = fin + tList[sentence][word][letter] #找出题中要求的字母
except IndexError:
fin = fin + ' ' #如果字母不存在则用空格替代
print(fin)
示例程序依旧是同学的参赛程序,但和我的思路基本一致,并且做好了注释,为这位同学点赞
|
|