英文分词相比中文分词要简单得多,可以根据空格和标点符号来分词,然后对每一个单词进行词干还原和词形还原,去掉停用词和非英文内容。词干还原算法最经典的就是波特算法(Porter Algorithm官网http://tartarus.org/~martin/PorterStemmer/ )
Java版的波特词干提取算法代码如下:
import java.io.*;
/**
* 实现波特词干提取算法,将一个单词转换为它的原型。
*/
class PorterStemmer{
private char[] b; /* 用来存待词干提取的单词(以char的形式) */
private int i, /* b中的元素位置(偏移量) */
i_end, /* 要抽取词干单词的结束位置 */
j, k;
private static final int INC = 50;/* 随着b的大小增加数组要增长的长度(防止溢出) */
public PorterStemmer(){
b = new char[INC];
i = 0;
i_end = 0;
}
/**
* 增加一个字符到要存放待处理的单词的数组。添加完字符时,
* 可以调用stem(void)方法来进行抽取词干的工作。
* @param ch 字符
*/
public void add(char ch){
if (i == b.length){
char[] new_b = new char[i+INC];
for (int c = 0; c < i; c++) new_b[c] = b[c];
b = new_b;
}
b[i++] = ch;
}
/**
* 增加字符数组ch到存放待处理的单词的数组b
* @param ch 字符数组
*/
public void add(char[] ch){
add(ch,ch.length);
}
/**
* 增加wLen长度的字符数组到存放待处理的单词的数组b。
* @param w 字符数组
* @param wLen 数组长度
*/
public void add(char[] w, int wLen){
if (i+wLen >= b.length){
char[] new_b = new char[i+wLen+INC];
for (int c = 0; c < i; c++) new_b[c] = b[c];
b = new_b;
}
for (int c = 0; c < wLen; c++) b[i++] = w[c];
}
/**
* 返回单词的词干。
*/
public String toString() { return new String(b,0,i_end); }
/**
* 返回单词的词干的长度
*/
public int getResultLength() { return i_end; }
/**
* 返回单词的词干char[]
*/
public char[] getResultBuffer() { return b; }
/**
* cons(i):参数i:int型;返回值bool型。当i为辅音时,返回真;否则为假
* @param i b数组下标
* @return cons(i) 为真 <=> b[i] 是一个辅音
*/
private final boolean cons(int i){
switch (b[i]){
case 'a': case 'e': case 'i': case 'o': case 'u': return false;
//y开头,为辅;否则看i-1位,如果i-1位为辅,y为元,反之亦然。
case 'y': return (i==0) ? true : !cons(i-1);
default: return true;
}
}
/**
*/
/**
* m():返回值:int型。表示单词b介于0和j之间辅音序列的个数。
* 现假设c代表辅音序列,而v代表元音序列。<..>表示任意存在。于是有如下定义:
<c><v> 结果为 0
<c>vc<v> 结果为 1
<c>vcvc<v> 结果为 2
<c>vcvcvc<v> 结果为 3
....
* @return 单词b介于0和j之间辅音序列的个数
*/
private final int m(){
int n = 0;//辅音序列的个数,初始化
int i = 0;//偏移量
//<c>
while(true){
if (i > j) return n;//如果超出最大偏移量,直接返回n
if (!cons(i)) break; //如果是元音,中断
i++; //辅音移一位,直到元音的位置
}
i++;//移完辅音,从元音的第一个字符开始
while(true){ //循环计算vc的个数
//<v>
while(true){ //循环判断v
if (i > j) return n;
if (cons(i)) break; //出现辅音则终止循环
i++;
}
i++;
n++;
//<c>
while(true){ //循环判断c
if (i > j)