字符串是一种最基本的数据结构。
问题1(单词级别):对文档中每个单词出现次数进行统计。例如圣经中大约有29131个不同的单词,统计其出现次数。
(1)用标准模板库的映射结构map来实现:set,map等容器一般是用平衡树来实现的。
(2)用散列表结构来实现:使用离29131最近的素数29989作为散列表大小。散列表结点包含指向单词的指针、单词出现频率以及指向下一结点的指针。散列函数通过一个乘数MULT把每个单词映射为一个小于29989的正整数(即在散列表中的地址)。
问题2(短语级别):给定一个文本文件,查找其中最长的重复子字符串。例如banana的最长重复串为ana。输入字符串存储在c[0...n]中。
(1)用穷举策略来实现:由于算法查看所有的字符串对,故时间为O(n**2),n为整个文件中的字符个数。
(2)用后缀数组来实现:后缀数组a是字符指针数组,指向了字符串的每一个后缀串。a[0]指向整个字符串以c[0],a[1]指向从第二个字符开始的后缀串(即指向c[1]),依此类推。如果某个串在c中出现两次,那么它将出现在两个不同的后缀中。因此对数组a排序后,就可以扫描数组,通过比较相邻元素来找出最长的重复字符串。假设文本不超过5MB。
由于排序的存在,算法需要O(nlogn)运行时间,以及额外的n个指针空间。
问题3(文本级别):根据输入的文档生成一段随机文本。为使生成的文本接近英文文本,把每个字母设置为其前k字母的函数,我们称为生成k阶文本。比如对2阶文本,th在英文中后面通常跟a, e,i,o,u和y,而跟r和w可能性小一些,跟其他字母的情况很少。这样就能保证生成文本比较接近英文文本。
可以采用后缀数组word来实现,不过数组指向从文档中单词的边界开始,即下一个数组元素指向下一个单词的开始处,而不是下一字符。word相当于指向了文档的每一个后缀短语,读完输入后,对word数组按k连短语(即含有k个单词的短语)进行排序。接着对输入文件的第一个短语,使用二分搜索找到其在word数组中的第一次出现,然后扫描所有相同的短语,并以相同的概率从这些相同的短语中随机选择一个短语,输出这个短语的第k个单词。这里我们设定输出的随机文本总共有10000个单词。
关键算法设计思想:字符串数据结构、映射结构(名字-值对)、散列表结构、平衡树、后缀数组、穷举策略。