输⼊
保证输⼊的字符中只出现以下字符:
- ⼤⼩写字⺟
- '-'连接符(减号)
- 逗号’,’
- 句号’.’
- 感叹号’!’(半⻆英⽂感叹号) (new!)
- 问号’?’(半⻆英⽂问号) (new!)
- 回⻋
连接符的说明
- 连接符 可以 出现在⼀⾏⼀个单词中间,如:post-graduate,这样算
作⼀个单词(不忽略’-’,具体请看例⼦)⽽不是两个分开的单词 - 连接符 不会 出现在单词的 第⼀个字符或最后⼀个字符 ,即 保证输⼊
中 不存在形如 -all 或者 post- 的单词 - 忽略连接符的情况:连接符 也可以 出现在⾏末,⽤来连接下⼀⾏的第
⼀个字符串(保证输⼊中 下⼀⾏只会以字⺟开头或为空),并视为 ⼀
个单词 ,统计此单词时应 忽略 此连接符 - 每个单词中最多出现⼀个连接符(第⼀种连接符),即统计后单词表中不
存在形如aaa-bbb-ccc-ddd…的单词
时,
输出格式
将文本的每个单词转成全⼩写,并按字典序输出单词和词频以及出现位置
每n+1⾏输出⼀个单词的信息,n为该单词出现次数,格式为
思路
如果是人来做文本的词频统计和位置统计,肯定是一边读文本一边统计。但实际上这里面包含两个步骤,单词分割和统计。如果一边分割一边统计,会导致代码间相互耦合,可读性也差。所以将两部分分开。
实际上,因为要统计位置而且存在换行连接符,所以其实还有一个单词组合的步骤,就是将之前分割出来的单词,如果是因为换行连接符分割成两个或更多单词(一个单词跨多行的情况),就将这两个单词组合。
也就是说: 单词分割, 单词组合, 统计
具体实现(Java)
类的设计:
这里只给出不完整的示意代码,具体实现看个人。
1.定义一个Word类
private String rawword; //原始单词
private String lowword; // 转换为小写后的单词
private ArrayList<Integer> row; // 单词出现的各行数
private ArrayList<Integer> col; // 单词出现的各列数
private int num; // 单词出现次数
- 定义一个Line类。
private String rawline; // 每一行的原始字符串
private int row; // 行号
private Words[] words; //用正则表达式“[ \t\n,.!?]+”分割出单词
注:在分割单词之后,使用IndexOf分别找出个单词的位置,并生成Word类的实例。注意要保证每次开始匹配的位置要在上一次匹配到的单词之后。防止出现
test test这样同一行出现两个相同单词的情况。
- TreeMap类
考虑到要求输出有序,使用lowstr - Word 作为键值对,TreeMap自动排序。
算法
1.单词分割:分别将文本的每一行生成Line()的实例。
2.单词组合:将所有的Line()的Words实例域组合成一个大的链表(Java内置的LinkedList),因为合并时要删除单词,使用链表比较方便。如果某个单词以‘-‘结尾,则与后面的单词合并,如果合并后的单词仍是’-'结尾,则再合并。
3.统计: 将上述链表中元素逐个添加如TreeMap即可。若TreeMap中已存在要添加的key了,则取出对应的value,将value的num++; row,col各增加一个,再放回去即可。