SDE / NG · Coding / OA

Amazon OA:IP 黑名单 * 匹配与最近五次请求限频

点号按字面处理,独立核对通配匹配和短请求窗口,不让被屏蔽请求消失。

题目重点:点号按字面处理,独立核对通配匹配和短请求窗口,不让被屏蔽请求消失。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练最近5次包含当前请求;题目未明确当前是否算入,正式题须核对,前5次口径作为待核变体。
  • 所有请求进入频次窗口,不以是否blocked过滤;*匹配任意长度字符串含空串,完全匹配整个IP文本。
  • 不进行IP规范化或octet范围校验,题目把IP作为字符串,点号仍是字面。

解题路线

  1. star_match用DP,previous[i]表示此前pattern可匹配text前i字符。普通字符来自previous[i-1]且字面相等;*来自previous[i](空)或current[i-1](多吃一个)。
  2. 初始化空pattern只匹配空text,*可以让current[0]延续空匹配。逐行只存两个长度L+1向量,支持连续多个*而不依赖正则特殊符号处理。
  3. 窗口deque维护最近5个请求,Counter同步增减;先放当前,再在超5时删最老项。blocked=黑名单任一匹配或counts[current]>2。
  4. 两层规则独立:黑名单命中依然应进入窗口计数,不能early return漏记请求。若实际合同是“之前5个”,应先查询过去窗口后插当前,而不是只改阈值。
  5. 模式量很大可预编译自动机/索引与cache,但缓存匹配结果不缓存请求限频结果,后者随历史变化;本训练基线先把语义核对正确。

手动走一遍

训练pattern="121.*"能匹配"121.3",不能匹配"121X3";requests=[a,a,a,b,c,a]最近5含当前时第3个a blocked,最后窗口[a,a,b,c,a]也blocked;若是前5合同,第3个尚只有2次历史a会不blocked。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

from collections import Counter,deque


def star_match(text,pattern):
    """Only * is special; . and every other character are literal."""
    previous=[True]+[False]*len(text)
    for ch in pattern:
        current=[previous[0] and ch=='*']+[False]*len(text)
        for i,value in enumerate(text,1):
            current[i]=(previous[i] or current[i-1]) if ch=='*' else previous[i-1] and ch==value
        previous=current
    return previous[-1]


def blocking_flags(requests,blacklist):
    """Recent five includes current request, all requests count including blocked ones."""
    window=deque()
    counts=Counter()
    output=[]
    for ip in requests:
        window.append(ip)
        counts[ip]+=1
        if len(window)>5:
            removed=window.popleft()
            counts[removed]-=1
            if not counts[removed]:del counts[removed]
        output.append(int(counts[ip]>2 or any(star_match(ip,pattern) for pattern in blacklist)))
    return output

复杂度

请求N、模式P、平均文本L、pattern长M,DP匹配最坏O(N·P·L·M),O(L)临时空间;窗口更新期望O(1)、大小≤5。提前规范化或自动机需另述成本。

易错点与追问

容易失分的边界

  • 点号当正则任意字符。
  • blocked请求不进窗口。
  • 每IP最近5条代替全局最近5请求。
  • 前5和含当前5混淆。

继续深挖

  • 前5口径怎样写独立测试?
  • IPv6不同写法是否规范化?
  • 许多pattern怎样预处理而不引入regex注入?
✓已复制微信号!