東京大学 情報理工学系研究科 コンピュータ科学専攻 2015年8月実施 専門科目II 問題3
Author
祭音Myyura (co-authored with GPT 5.6 SOL)
Description
设字符集 Σ 的大小为 m,字符串集合 S={w1,…,wn} 中字符串的平均长度为 ℓ;输入查询串 w 的平均长度也为 ℓ。需要判断 w∈S。必要时可自行引入参数。以下用
S0={CAT,CAP,CAPE,REASON,RAINBOW}
作为例子。
(1)用字符串对象的链表表示 S,给出内存量和平均查询复杂度。
(2)用开放寻址哈希表表示 S,给出内存量、平均查询复杂度,并定义一种哈希函数。
(3)用按字典序比较字符串的二叉搜索树表示 S,回答同样问题;按给定顺序插入 S0 并画出树。
(4)用 trie 表示 S。根到叶的路径对应一个字符串,每个内部结点保存含 m 个子指针的数组。回答同样问题并画出 S0 的 trie。
(5)当 ℓ≫n 时,trie 可能浪费内存。给出改进方法并举例说明。
(6)当 m 很大时,trie 也可能浪费内存。给出改进方法并举例说明。
Kai
以下把一次字符比较或一次机器字访问计为 O(1),并保留字符串本身的存储量。
(1)
字符串共占 Θ(nℓ),链表指针占 Θ(n),故总内存为
Θ(nℓ+n)。顺序查询平均检查 Θ(n) 个字符串,每次比较至多检查 Θ(ℓ) 个字符,故一般上界为
O(nℓ);最坏情况也为 Θ(nℓ)。
(2)
假设使用均匀散列模型。取表长 T=Θ(n) 并保持负载因子 α=n/T<1 为常数。可从合适的随机哈希族中选择多项式哈希
h(w)=j=0∑∣w∣−1code(wj)pjmodT,
冲突时按线性探测寻找下一个槽。内存为字符串的 Θ(nℓ) 加表槽的 Θ(n),即
Θ(nℓ+n)。计算哈希需 Θ(ℓ),期望探测次数为 O(1),所以平均查询时间为
Θ(ℓ)。
(3)
内存仍为 Θ(nℓ+n)。树高为 h 时查询需 O(ℓh);树平衡或插入次序随机时平均为
O(ℓlogn),退化时最坏为 O(nℓ)。
按题给顺序插入得到:
(4)
trie 至多有 1+nℓ 个结点;每个内部结点含 m 个指针,因此内存上界为
O(mnℓ)。查询只沿输入字符串走一遍,平均为
O(ℓ)。为处理一个字符串是另一个字符串前缀的情形,在结点上另设“单词结束”标记。
星号表示单词结束。
(5)
使用压缩 trie(radix tree / Patricia trie):把没有分支的连续结点压成一条带字符串标签的边。例如上图从根到 REASON 的长链可压成边 R 后接边 EASON,到 RAINBOW 的分支压成 AINBOW。
压缩后分支结点和边均为 O(n) 个;边标签可用“原字符串引用 + 起止下标”表示,只需 O(1) 附加空间。于是除保存原字符串的 Θ(nℓ) 外,树结构不再含 ℓ 倍的结点开销。
(6)
把每个结点的长度为 m 的稠密指针数组改为只保存现有边的稀疏字典,例如哈希表、平衡树或短有序表。根结点在本例中只保存
{C↦C,R↦R},而不是 m 个槽。
这样全部子指针数与实际边数同阶,即 O(nℓ);用哈希字典时查询仍为期望 O(ℓ),用平衡树时为 O(ℓlogm)。