本作业共 5 题,满分 40 分,内容包括位置索引、词典压缩、倒排记录表压缩、容错检索和向 量空间模型。答案应清楚、简洁;题目要求说明理由或列出计算过程时,请给出必要的步骤。 完成后将答案整理为 PDF,按指定的方式和截止时间提交。
一、位置索引(5 分)

1.位置索引 ☆☆☆

答案
输出格式示例:文档号: <word1位置, word2位置>, <word1位置, word2位置>。
2.临近查询 ☆☆☆

答案
邻近查询 "word1 /k word2" :要求 |word1 的位置 - word2 的位置| ≤ k。且先后顺序不限(即 word1 在 word2 前,或 word2 在 word1 前都可以)
-
查找文档1:
-
I在 1,student在 4。差值为 |1 - 4| = 3 > 2。(不匹配) -
I在 6,student在 4。差值为 |6 - 4| = 2 ≤ 2。(匹配,按先后顺序记录位置为 <4, 6>) -
I在 10,student在 13。差值为 |10 - 13| = 3 > 2。(不匹配) -
(
I在 10 和student在 4 差值更大,忽略)
-
-
查找文档2:
-
I在 1,student在 4。差值 |1 - 4| = 3 > 2。(不匹配) -
I在 5,student在 4。差值 |5 - 4| = 1 ≤ 2。(匹配,按先后顺序记录位置为 <4, 5>)
-
-
答案: 1: <4, 6>; 2: <4, 5> (注:位置对内部的顺序,一般按词在文中出现的先后顺序写)

3.位置索引扩展 ☆☆☆

答案
修改方案:
将原来的单一位置索引 (文档编号: <位置1, 位置2...>),改为包含句子编号的二元组位置索引 :
(文档编号: <(句子编号1, 词在句内位置1), (句子编号2, 词在句内位置2)...>)
文档 1 处理:
-
句子 1:
I am a student, and I currently study retrieval.(句号结束) -
句子 2:
I was a student in Beijing last quarter.
文档 2 处理:
-
句子 1:
I was a student.(句号结束) -
句子 2:
I have studied retrieval.
接下来,我们采用 (文档编号, 句子编号, 词在句内的位置) 的三元组格式来列出倒排记录表

二、词典存储压缩(10 分)

1.前端编码 ★★☆

答案
这个做一遍就会。
方法
先按字典排序->看块大小。
块内第一个全部保留,然后对比前后两个词,一样的部分用*◇代替,补上后缀。

(1)每块包含 3 个词项
我们需要把排好序的 6 个词分成两块。
-
第一块(前3个) :
eligible,elite,ellipse-
第 1 个词:完整保留
eligible -
第 2 个词:
elite与eligible的公共前缀是eli。编码为*◇te -
第 3 个词:
ellipse与elite的公共前缀是el。编码为*◇lipse -
连续字符串 :
eligible*◇te*◇lipse
-
-
第二块(后3个) :
elongate,elope,eloquent-
第 1 个词:完整保留
elongate -
第 2 个词:
elope与elongate的公共前缀是elo。编码为*◇pe -
第 3 个词:
eloquent与elope的公共前缀是elo。编码为*◇quent -
连续字符串 :
elongate*◇pe*◇quent
-
答题格式:
第一块:eligible*◇te*◇lipse
第二块:elongate*◇pe*◇quent
(2)每块包含 6 个词项
这就意味着所有的 6 个词都在同一个块里(或者说是一个块)。
-
第 1 个词:
eligible -
第 2 个词:
elite。与上一个词eligible公共前缀eli,编码为*◇te -
第 3 个词:
ellipse。与上一个词elite公共前缀el,编码为*◇lipse -
第 4 个词:
elongate。与上一个词ellipse公共前缀el,编码为*◇ongate -
第 5 个词:
elope。与上一个词elongate公共前缀elo,编码为*◇pe -
第 6 个词:
eloquent。与上一个词elope公共前缀elo,编码为*◇quent
答题格式:
eligible*◇te*◇lipse*◇ongate*◇pe*◇quent
2.词典数据结构 ★★☆


答案
首先,梳理题目给出的基本假设(以字节为单位):
-
词典需要保存:词项 、文档频率 、指向倒排记录表的指针。
-
固定开销:文档频率(4字节)+ 倒排记录表指针(4字节)= 8字节/每个词项。
-
字符开销:每个字符占 1字节 ,符号
*和◇也各占 1字节。 -
词项总数:6个。
(1)定长存储的计算
-
设定:词项字符串使用 20 字节的定长字段。
-
单个词项的开销 :词项字段(20) + 文档频率(4) + 倒排指针(4) = 28 字节。
-
总词项数:6个。
-
总字节数 : 6 × 28 = 168 字节。
(2)分块存储并采用前端编码的计算
根据上一题(小块每块3个词项)的结果:
-
第 1 块:
eligible*◇te*◇lipse -
第 2 块:
elongate*◇pe*◇quent
第一部分:词项字符串本身的字节数
- 所有字符总长 = 19 + 19 = 38 字节。
第二部分:附加信息开销(这部分不变)
-
每个词项的基础信息(文档频率+倒排指针) :6 个词项 × (4+4) = 48 字节。
-
块指针开销 :2 个块 × 3 字节 = 6 字节。
重新计算总字节数:
总字节数 = 字符总长(38) + 基础信息(48) + 块指针(6) = 92 字节。
重新计算节约比例:
-
定长存储总空间:168 字节
-
压缩后总空间:92 字节
-
节省的字节数:168 - 92 = 76 字节
-
节省比例 = 76 / 168 = 19 / 42 ≈ 45.24%


3.词典压缩后寻址能力★☆☆

答案

三、倒排记录表压缩(8 分)

1.可变字节编码 ★★★

答案
AI给的答案和课件有出入,以课件为准。
变长字节码
高频词差值是小数,用一个字节即可。七位存数值,一位结束标识符
低频词差值是大数(稀疏),分组00011010 01110101(最后的1代表结束位)



2.γ编码 ★★☆

答案
编码按照<长度,偏移>格式书写。
偏移是去掉首个1剩下的部分。长度是偏移长度的一元码(即几个1+一个0)。



3.传输时间计算 ☆☆☆

答案


4.可变字节编码的最大平均解码时间 ★☆☆

答案


四、容错检索(7 分)

1.字符二元组索引 ★★☆

答案
提取字符二元组(k=2):
-
$peter$→→$p,pe,et,te,er,r$ -
$piper$→→$p,pi,ip,pe,er,r$ -
$picks$→→$p,pi,ic,ck,ks,s$ -
$papers$→→$p,pa,ap,pe,er,rs,s$
(1)有多少个不同的字符二元组词典项?
去重后,所有的二元组包括:$p, pe, et, te, er, r$, pi, ip, ic, ck, ks, s$, pa, ap, rs。
一共有 15 个不同的二元组词典项。
(2)对应的倒排记录共有多少条?
由于每个二元组在它出现的每个词项中都会生成一条倒排记录(假设每个词项视为一篇文档,记录就是对应的文档ID),我们只需统计 4 个词项包含的二元组总数。
-
$peter$包含 6 个 -
$piper$包含 6 个 -
$picks$包含 6 个 -
$papers$包含 7 个(注意长度)总记录数 = 6 + 6 + 6 + 7 = 25 条。

2.最优 AND 查询表示 ★☆☆

答案
通配符 p*er 的意思是:以 p 开头,以 er 结尾。
在带边界符的二元组索引中:
-
以 p 开头 :对应二元组
$p -
包含 er :对应二元组
er -
以 er 结尾 :对应二元组
r$(因为er后面必须紧跟结尾符$)

3.累计需要遍历的倒排记录数 ★☆☆

答案
题目要求:每次只能处理两个倒排表,且必须遍历两个表中的全部记录。我们要计算最坏情况(或最优合并策略下)的总遍历记录数。
采用从短到长的合并策略最省时:
-
第 1 步 :合并
r$(2条) 和er(3条)。-
需要遍历:2 + 3 = 5 条记录。
-
合并结果(交集):{peter, piper} (共 2 条记录)。
-
-
第 2 步 :将上一步的结果 {peter, piper} 与
$p(4条) 合并。-
需要遍历:2 + 4 = 6 条记录。
-
合并结果:{peter, piper}。
-
累计遍历记录数 = 5 + 6 = 11 条。
(简要说明:采用先合并最短倒排表 r$ 和 er,再将结果与 $p 合并的策略,可以有效减少总遍历量。)

4.轮排索引 ★★☆

答案
计算过程:
根据第一题的要求,我们在建立索引时在词项首尾都加了 $ 符号。轮排索引的构建方法是:将加了边界符的词项不断将首字母移至末尾,直到循环一周回到起点。
轮排项的数量等于该词项(含边界符)的总字符长度。
-
peter→→$peter$:长度为 7(生成 7 个轮排项) -
piper→→$piper$:长度为 7(生成 7 个轮排项) -
picks→→$picks$:长度为 7(生成 7 个轮排项) -
papers→→$papers$:长度为 8(生成 8 个轮排项)
总轮排词典项数 = 7+7+7+8=7+7+7+8= 29 个。

为什么要轮排索引
1. 为什么普通索引不够用?(痛点)
在普通的倒排索引(或词典树 Trie)中,只能高效地处理"前缀查询"。
-
如果你查
p*(以 p 开头的词),系统很快就能顺着树找到所有分支。 -
如果你查
p*er(以 p 开头,er 结尾),普通词典就傻眼了。它只能把词典里所有以p开头的词全部拉出来,然后挨个检查词尾是不是er。如果词典很大,这种全表扫描会极慢。
2. 轮排索引是如何破局的?(原理)
轮排索引通过**"旋转"** ,把所有可能出现在词尾的字符,都转到了词首。
以 peter 为例,加上边界符变成 peter$,旋转后生成:
peter$, eter$p, ter$pe, er$pet, r$pete, $peter
神奇的事情发生了:
当你想查 p*er(以 p 开头,以 er 结尾)时,你给它加上 $ 变成 p*er$,然后把 * 后面的内容转到前面,变成 er$p* 。
这时候,你只需要在轮排索引里找以 er$p 开头的词条就行了。
-
peter$的旋转序列中,刚好有er$pet。 -
piper$的旋转序列中,刚好有er$pip。
优势:原本极其耗时的"后缀匹配"或"中间匹配",瞬间变成了最高效的"前缀匹配"。
轮排索引的三大显著优势:
-
极高的检索效率
将最坏情况为 O(N)O(N) 的全表扫描,降级为了 O(logN)O(logN) 或 O(1)O(1) 的字典查找(依赖于底层使用的是 B-Tree、哈希表还是 Trie 树)。
-
支持任意位置的单一通配符
无论是前缀通配
*abc、后缀通配abc*,还是中间通配a*c,只要有一个*,通过旋转都能完美转化为前缀查询。 -
实现门槛低
底层的字典结构(如 B+ 树)不需要任何修改,只要在写入词典前把词项旋转好存进去,查询时把 Query 旋转好去查即可。
但轮排索引也有"致命缺点"(为什么现在用得不多):
既然这么好,为什么现在的搜索引擎(比如百度、Google)不把它作为唯一的通配符解决方案呢?
-
空间膨胀(词典爆炸)
一个长度为 LL 的词,会产生 LL 个轮排项。如果词典有 100 万词,平均长度 10,那么词典瞬间变成 1000 万项。内存/磁盘开销巨大。
-
无法处理多通配符
如果用户查
p*r*er,轮排索引就崩溃了。因为无法通过旋转转成一个前缀。遇到这种情况,只能拆解枚举,比如转成p*AND*r*AND*er,然后在求交集,效率极其低下。
5.轮排索引的使用 ★★☆

答案
在轮排索引中处理通配符查询 p*er,规则是:在词尾加上 $,然后将 * 及其后面的部分移动到词首。
-
原查询:
p*er -
加边界符:
p*er$ -
旋转(把
*及后面部分移到前面):er$p*

五、向量空间模型(10 分)


1.词频TF 词项在文档中出现的次数 ★★☆

答案
词频(Term Frequency, TF)是指某个词在文档中出现的次数。
-
文档 A (共 6 个词):
to(2次),be(2次),not(2次) -
文档 B (共 5 个词):
it(1次),was(1次),not(1次),to(1次),be(1次)
答案格式:
-
文档 A :
to: 2, be: 2, not: 2 -
文档 B :
it: 1, was: 1, not: 1, to: 1, be: 1

2.二元组词频 ★★☆

答案
词二元组就是将相邻的两个词组合在一起。
-
文档 A 的二元组:
-
to be(出现 2 次,位置1-2,4-5) -
be not(出现 2 次,位置2-3,5-6) -
not to(出现 1 次,位置3-4)
-
-
文档 B 的二元组:
-
it was(出现 1 次,位置1-2) -
was not(出现 1 次,位置2-3) -
not to(出现 1 次,位置3-4) -
to be(出现 1 次,位置4-5)
-
答案格式(汇总列出):
-
文档 A :
to be: 2, be not: 2, not to: 1 -
文档 B :
it was: 1, was not: 1, not to: 1, to be: 1

3.词频向量空间模型 ★★★

答案
需要先集成Q2的不重合二元组。作为维度。
然后计算各文档的TF词频。
然后计算欧氏距离。
然后归一化。按格式作答。


4.TF-IDF向量空间模型 ★★★

答案
分开计算。
先计算IDF=log10(N/df)。
df是包含该词的文档数。 tf为在文档d中出现的次数。
计算w=tfXidf
计算w欧氏距离,归一化。按格式作答。


5.TF和TF-IDF向量空间模型的区别 ★★☆

答案


