简介
上章简单聊了下爬虫,因为我用的是java,使用jsoup就可以简单实现,最多加个多线程抓取就行,感觉没啥好说的,具体的爬虫实现大家看看别的文章就好。
中文分词就是将一篇文档分成若干字、词,便于之后创建索引文件。分词方法主要有机械匹配算法、统计方法以及基于理解的分词算法。
其中机械匹配算法主要有正向最大匹配和逆向最大匹配,这两个的区别就是匹配的方向不同,正向是从左往右,逆向则是从右往左。除了方向不同,这两种的基本思路都一样,都是先找到一个可以匹配的最大字符串,比如给定最大词语的长度为3,则正向或逆向地找到3个长度的词是否存在于词库,存在就说明匹配成功,反之,则将长度减一继续匹配,直到长度为1时,直接匹配成功,即所有单字都可以匹配成功。
下面举个例子,假如词库中存在如下词语:火柴、小女孩、可怜、真可。
例句:卖火柴的小女孩真可怜。
正向匹配:卖/火柴/的/小女孩/真可/怜。
逆向匹配:可怜/真/小女孩/的/火柴/卖。
逆向最大匹配算法
具体算法
1、从起始位置逆向或正向找到最大长度的字符串,是否匹配,是则将起始位置更改为原起始位置减去或加上(逆向为减,正向为加)最大字符串长度,继续进行步骤1操作;否则,进行步骤2操作。
2、将字符串长度减1,字符串长度是否为1,是则跳到步骤3。是否匹配,是则将起始位置更改为原起始位置减去或加上现字符串的长度,进行步骤1操作;否则,继续进行步骤2操作。
3、单字匹配成功,起始位置更改为原起始位置减或加1。
具体实现
/**
* 逆向最大匹配
* @param sentence 句子
* @param maxL 词语最长
* @return Stack<HashMap<String,Integer>> result
*/
private Stack<HashMap<String,Integer>> reverseMaxMatch(String sentence, int maxL) {
Stack<HashMap<String,Integer>> result = new Stack<>();
for(int j = sentence.length(); j > 0;) {
HashMap<String,Integer> word = new HashMap<>();
if(j < maxL) { //小于MAX两种情况:1.本身小于 2.减到最后小于
maxL = j; //更改最长词语长度为j
}
String subWord = sentence.substring(j - maxL, j);
if(isWordMatch(subWord)) { //subWord是否匹配? 单字都匹配
word.put(subWord,j);
result.push(word);
j -= maxL;
}else {
String tempWord = "";
int k;
for(k = maxL - 1; k > 0; k--) {
tempWord = subWord.substring(maxL - k, maxL);
if(isWordMatch(tempWord)) {
break; //tempWOrd匹配就跳出循环,全部单字均匹配
}
}
if(k == 0) k = 1;
word.put(tempWord,j);
result.push(word);
j = j - k;
}
}
return result;
}
其中boolean isWordMatch(String word)方法是用于匹配word是否位于词库的方法,返回的数字指这个词在句子里的最后的位置,减去词长可以得到词的初始位置。