P12877 [蓝桥杯 2025 国 Python A] 心意 题解
P12877 [蓝桥杯 2025 国 Python A] 心意 题解
这是一篇 Python 的偷鸡做法,看似绿题,实则绿的点只在于打出 KMP 板子。由于 Python 已经帮我们造好了轮子,我的评价是:建议降红。
0x01 分析
首先,题目中的旋转,可以注意到其实就是环形地向左平移,于是我们只需要破环成链——直接将
考虑如何将匹配的复杂度降下来……等等,说到匹配,如果能使用 KMP 算法,复杂度就可以降到
仔细再想想这句话,实际上能否匹配成功与
0x02 实现
Talk is cheap, show me the code!
Python 中的 KMP 算法实现为str类的find方法,通过调用内置的help(str.find)可以得到相关信息(已翻译):
find(self, sub[, start[, end]], /) builtins.str 方法
返回 S 中找到子串 sub 的最小索引,使得 sub 包含在 S[start:end] 之间。
可选形参 start 和 end 与切片表示法一致。
失败时返回 -1。
码量少,好写,去掉注释和空行仅有 22 行。
n = int(input())
a = list(map(int, input().split()))
b = list(map(int, input().split()))
# 计算差分数组
differenceA, differenceB = [], []
# 特判第一个数字
differenceA.append(a[0] - a[n - 1])
differenceB.append(b[0] - b[n - 1])
for i in range(1, n):
differenceA.append(a[i] - a[i - 1])
differenceB.append(b[i] - b[i - 1])
# 破环成链
differenceA += differenceA
# 为了方便查找,将差分数组转换为字符串
stringA = ','.join(map(str, differenceA))
stringB = ','.join(map(str, differenceB))
# 核心算法:字符串匹配
result = stringA.find(stringB)
if result == -1: # 若不存在则输出 -1
print(result)
else:
# 接下来我们需要找到下标 result 对应的是第几个数字
currentPosition = 0 # 表示字符串中的位置
for index, number in enumerate(differenceA):
if currentPosition == result:
print(index)
break
currentPosition += len(str(number)) + 1
0x03 总结
最慢时间 720ms,最大内存 145MB。另外,使用 PyPy 3 会负优化 T 掉(我也不知道为啥)。
这题其实不难想,只需要差分转化,正如开头所说,核心其实是 KMP 算法。玩 Python 想要偷鸡,同样需要对内置函数及标准库足够熟悉。如果考场上真忘了怎么用,就打开 Python 安装目录下的/Doc/html/index.html吧,尤其是 Library reference 板块,它会告诉你一切的。