BM85 验证IP地址¶
中等通过率 18.01%python3核心代码模式样例通过牛客 AC字符串
讲解章节:字符串处理
一句话
按分隔符分流,再把题面的每条规则逐条翻译成逐段体检。
解题思路¶
这题考什么¶
没有算法成分,考的是把一份自然语言规格不重不漏地落成判断, 以及分清哪些规则在 IPv4 与 IPv6 之间恰好相反。 题面开头声明「本题对 IPv4、IPv6 的描述若和真实情况有出入,以本题描述为准」, 所以一切以题面为准,不要凭 RFC 的印象补规则: 真实世界的 IPv6 允许用 "::" 缩写连续的零段,本题明确判它不合法。
先按分隔符分流:含 "." 走 IPv4 校验,含 ":" 走 IPv6 校验, 两条都不通过就是 Neither。
IPv4:用 "." 切开必须恰好 4 段,每段满足
非空 "1..1.1" -> Neither
只含 0-9 "1.1.1.a" -> Neither
长度 <= 3 "1.1.1.1234" -> Neither
无前导零("0" 本身合法) "172.16.254.01" -> Neither
数值 0 <= x <= 255 "256.256.256.256" -> Neither
IPv6:用 ":" 切开必须恰好 8 段,每段长度落在 1..4 之间, 且只含十六进制字符 0-9 / a-f / A-F,大小写都认。 长度下限 1 挡住空段(也就是题面点名的 "::"), 长度上限 4 挡住「多余的 0」("02001" 有 5 位)。
段内前导零在 IPv6 里是允许的("0db8"、"0" 都合法),与 IPv4 恰好相反, 这是两套规则最容易互相写串的一处。
数据规模与复杂度¶
串长 5 <= n <= 50,时限「其他语言 2 秒」,规模上毫无压力: 时间 O(n)、空间 O(n)(切分出来的那几段)。 这题的失分全在规则覆盖度上——通过率 18%,低于同题单里不少算法题, 掉的分几乎都是漏判某一条边界。
坑在哪¶
- 判十进制数字不要用 str.isdigit():它对 "²"、"١" 这类 Unicode 数字字符 也返回 True,后面的 int() 未必吃得下。对着显式字符集判既稳妥, 又不依赖运行环境的 locale。
- IPv4 的前导零判断必须写成「首位是 0 且长度大于 1」两个条件相与。 只判首位是 0 会把合法的单个 "0" 毙掉;只判数值范围则拦不住 "01"。
- IPv6 段长的下限与上限对应两条独立的题面规则(不许空段、不许多余的 0), 漏掉任何一边就会放过 "2001:0db8:85a3::8A2E:0370:7334" 或 "02001:0db8:85a3:0000:0000:8a2e:0370:7334"。
- 段数判断顺手覆盖了首尾分隔符:"1.1.1.1." 会切出 5 段,段数关就过不去, 不必再额外写 startswith / endswith 的判断。
- 分流用 in 而不是二选一:一个串同时含 "." 和 ":" 时两套校验都会跑, 但 IPv4 要求每段只含数字(不可能带冒号),两边不可能同时通过, 最终仍正确地落到 Neither。
参考实现¶
[:octicons-arrow-left-16: BM84](BM84.md) [BM86 :octicons-arrow-right-16:](BM86.md)