通过率 0% · 提交 0 · 通过 0
这道 OJ 的配套动画
Prefix Cache 调度器 · 对应本题的思路、过程和代码
推理服务维护 S 个 Prefix Cache 槽位,每个槽位保存一段 token 序列和当前负载。每来一个请求,需要选择一个槽位复用最长公共前缀;如果多个槽位的公共前缀长度相同,选择当前负载更小的槽位;仍并列则选择编号更小的槽位。请求处理后,该槽位的负载增加未命中的 token 数,并将缓存序列更新为本次请求序列。
这类题属于算法机考高频题型中「华为 AI 岗 / KV Cache」方向的高频题型,通常考察对「华为 AI 岗 / KV Cache」的建模能力与边界条件处理。掌握本题的解题思路后,可举一反三应对同类真题方向,稳步提升机考通过率。
第一行输入 S Q。接下来 S 行,每行输入 load len 和 len 个 token,表示一个缓存槽位。随后 Q 行,每行输入 len 和 len 个 token,表示一个请求。
输出 Q 行。每行包含选择的槽位编号和复用的前缀长度。槽位编号从 1 开始。
1 <= S <= 500;1 <= Q <= 500;1 <= len <= 60;0 <= load <= 1000000;token 为 32 位整数。
示例 1
输入示例
3 2 3 3 1 2 3 1 3 1 2 4 0 1 9 3 1 2 5 2 9 8
输出示例
2 2 3 1
选择最长公共前缀
示例 2
输入示例
2 1 5 3 4 5 6 2 2 4 5 3 4 5 6
输出示例
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
训练营动画视频讲解
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
1 3
完全命中缓存
时间限制 3000 ms · 内存限制 256 MB
这些是真正决定能不能 AC、但通用题解里常被略过的点。
对每个请求,分别计算它与每个缓存槽位序列的最长公共前缀长度。选择前缀命中长度最大的槽位;若并列,选择当前负载较小的槽位;仍并列时选择编号较小的槽位。选中后,槽位负载增加“请求长度减命中前缀长度”,并用本次请求的完整 token 序列替换该槽位缓存。
最长公共前缀准确表示可复用的 token 数,请求剩余部分就是新增计算量。三级比较依次落实命中优先、负载均衡和稳定编号规则,因此选中的槽位唯一符合题意。更新负载和缓存后,下一次请求读取到的状态与调度过程一致。
设槽位数为 S、单次请求与缓存序列最大长度为 L、请求数为 Q。逐槽位比较前缀的总时间为 O(QSL);保存全部缓存最多占 O(SL) 空间。
空前缀的命中长度为 0;完全命中时新增负载为 0。每次处理后缓存应整体替换为当前请求,不能只追加未命中的后缀。
# 逐槽位算最长公共前缀,比较键=(-前缀长,负载,编号)取最小;
# 选中后负载加未命中数(请求长−前缀长),缓存序列整体替换为本次请求。
import sys
def lcp(a, b):
i = 0
limit = min(len(a), len(b))
while i < limit and a[i] == b[i]:
i += 1
return i
def solve() -> None:
data = list(map(int, sys.stdin.buffer.read().split()))
if not data:
return
at = 0
s = data[at]; at += 1
q = data[at]; at += 1
slots = []
for _ in range(s):
load = data[at]; at += 1
length = data[at]; at += 1
seq = data[at:at + length]; at += length
slots.append([load, seq])
ans = []
for _ in range(q):
length = data[at]; at += 1
req = data[at:at + length]; at += length
best = 0
best_prefix = -1
for i, (load, seq) in enumerate(slots):
prefix = lcp(seq, req)
if prefix > best_prefix or (prefix == best_prefix and (load < slots[best][0] or (load == slots[best][0] and i < best))):
best = i
best_prefix = prefix
ans.append(f"{best + 1} {best_prefix}")
slots[best][0] += len(req) - best_prefix
slots[best][1] = req
print("\n".join(ans))
if __name__ == "__main__":
solve()