题目重点:区分给定子串的成员查询和枚举全部匹配,选择对应索引并计算字符串成本。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 可辨问点是判断当前substring是否在keyword list,未给子串边界/大小写规则。练习采用给定完整子串的精确成员查询,不自行改成“整句分词”或“列出全部匹配”。
- 关键词重复不影响布尔结果,空串是否有效由输入词表决定;不自动trim/lower破坏字面合同。
解题路线
- 少量单查询直接逐词比较,成本依词数量和比较字符;大量查询可预建set,平均查找探测接近常数,但计算子串hash仍要读字符,不能写整体O(1)。
- 词表固定时构set需读全部关键词字符,保留完整词用于碰撞相等比较。hash碰撞不应导致假匹配;只保存hash而不核文字不是精确成员集合。
- 若问题改成从某起点找所有词前缀,Trie沿字符走并在terminal返回匹配;若在全文任意起点多模式检索,再考虑Aho–Corasick等结构,输出合同和复杂度不同。
- substring复制本身可能O(L),输入可给范围视图或迭代匹配以减少复制,但Python普通切片会构造新字符串。对Unicode正规化选择要一致处理词表与查询,不能只处理一侧。
手动走一遍
词表[cat,car],给定cat返回true、ca返回false;Trie走到ca节点却不terminal,因此也不能把存在路径当完整词。词表含空串时空查询true,否则false。
规模与取舍
设关键词总字符D,set构建通常O(D),保留词及索引空间O(D+词数);长度L查询平均O(L)含hash/比较上界因素,最坏碰撞退化另计。枚举所有子串可产生Θ(N²)个范围,不因为每次set探测短就整体线性。
易错点与追问
容易失分的边界
- Trie存在前缀就当完整关键词。
- 忽略子串构造/hash成本。
- 把成员查询换成另一种分词输出却不先确认。
继续深挖
- 如果要求多个关键词连续覆盖整串,为什么需要额外DP而不是这份成员判断?
- 如果词表频繁更新,怎样保持索引版本与查询一致?
