题目地址:http://coursera.cs.princeton.edu/algs4/assignments/wordnet.html
1. 题目阅读
WordNet定义
WordNet是指一个包含唯一根的有向无环图,图中每一组词表示同一集合,每一条边v→w表示w是v的上位词。和树不同的地方是,每一个子节点可以有许多父节点。
输入格式
- 同义词表
文件中每行包含一次同义名词。首先是序号;然后是词,用空格分开。若为词组,则使用下划线连接词组。最后是同义名词的注释
36,AND_circuit AND_gate,a circuit in a computer that fires only when all of its inputs fire
- 上位词表
文件中包含序号i的上位词j。若有多个上位词,则使用空格分隔。
34,47569,48084
WordNet数据类型
需要实现
- 构造函数,通过同义词表和上位词表
- 迭代器
- 判断词是否在WordNet里
- 计算两个词的最短祖先路径距离
- 计算两个词的最短祖先路径
最短祖先路径是指两个点v、w到达相同点距离和最短的点x。
另外,还可以给定两个集合A、B,两个集合中的各自拥有一个点v、w到达相同点距离和最短的点,对比第一种,还需要从集合中找出合适的v、w。
SAP数据类型(最短祖先路径)
需要实现
- 构造函数
- 求两点的最短祖先编号、距离
- 求两集合的最短祖先编号、距离
Outcast detection
给定一串词,给出哪个词和其他词最不相关
2. 题目分析
按照我认为的实现顺序分析
SAP实现
构造函数:构造digraph
祖先编号,路径: 寻找两个点v、w到达相同点距离的最短点x。
第一步,对v、w进行BFS搜索,找到从v、w到其他点的最短距离。BFS是O(E + V)
第二步,将v、w到相同点的距离相加,若其中一个点不能到达,则这个点的最短祖先距离为-1。在这个遍历过程中,找到相加距离最短的点则为最短祖先距离。O(V)
整个算法性能:O(E + V)
卡在这里了一会,主要是读题目的checklist时候看到bfs当成深度优先了,然后思想就被禁锢dfs了
两个集合的最短祖先
两个集合两两求,找最小。感觉这个肯定超时了。但是感觉也只能这样。暂时用这个方法写。
正确实现方法:BFS提供使用一个集合作为参数构造BFS的,得到的是点到集合的最短距离,由于不需要输出路径,这里你可以认为一个集合就是一个点,就可以按照上面的方法来计算两个集合的最短祖先了。
WordNet实现
构造函数:文件读取,使用java的string分割。然后构造一个digraph。
关于文件存储
这里的输入都是string,不是序号,需要先将单词对应为序号。
构造一个类存储同义词集合,包括序号和单词。,第一句是错的,不需要构造这个,因为这里不需要知道一个序号下面有什么单词。第二句也是错的,因为sap的输出需要输出单词,还是需要构造一个map存序号和单词的关系。但是api只输出一个单词,不懂为什么。这里api是要输出那一串用空格分开的词。
同义词组:使用一个map存储单词所对应的序号。这里求出最大的序号,就知道digraph有多少个顶点,可以构造空digraph。
上位词关系:使用一个digraph存储
迭代器:返回map的key的迭代器
最短祖先路径、距离:调用sap
边界条件:判断是否有环,调用DirectedCycle类。判断是否有多个root,如果一个点有一个出的边,则不是root。
Outcast detection
构造函数:因为需要immutable,要拷贝WordNet。暂时先不考虑这个,直接引用参数里的wordnet。
上面直接引用没啥问题。java的immutable还是没太搞懂
outcast:计算每个输入词和其他词的距离,输出最大的
3. 第一次提交的问题
corner case的异常抛出不全
迭代器里有null的没考虑,isnoun参数为null没考虑
WordNet的sap返回值错误
应该返回所有的词,用空格分开,跟输入一样的方式,而不是只返回一个词。
集合的最短祖先求解超时
果然超时了。参考了别人的博文,直接使用BFS好像是不行的,需要自己实现才能解决时间。决定自己写了。
准备自己写BFS时,发现作者提供的BFS是有点到集合的最短距离的构造方法,用这个就可以。分析已经写在上文
4. 性能优化
参考
1.Programming Assignment 1: WordNet
原文地址:https://www.cnblogs.com/huipengly/p/9813571.html