📄 code1.txt
字号:
分词程序的改进版
这个版本的分词程序解决了一个新的问题,我将他称之为I.S.B.N问题,因为在使用中有达人反馈到前一个版本会将I.S.B.N分为四个词,这是不合适的,于是有了这个版本,可以处理这个问题。其实仅仅添加了前5行代码而已。思路很简单,将'.'去掉就可以了,那么I.S.B.N就变为了ISBN,就可以被整体识别了(因为是全大写的单词,可以整体被识别,也就是前一次提到过的NEC问题)。然而,有一个可能的bug:在两个句子之间,正常的句号也被删掉了。事实上,通常不会有问题,因为:1、正规书写规范中,句号后有一个空格,即使句号被删掉也没关系,可以借助那个空格分词;2、即时没有空格,误分几率也很低,因为通常句号前面是一个小写字母,句号后面是一个大写字母,即使连起来也可以被程序正常的作为两个词断开;3、可能出错的情况是如下:My ID is A.Your ID is B.显然,会出现AYour,那么也没关系,会自然的被分为A和Your两个词,因为这不是一个全大写的词,所以程序会把最后一个大写前面的所有字母都分开,于是也不会有错。总之这个程序现在看是比较完善的。不过有一个问题,形如:RDFSchema,这显然是RDF和Schema两个词,然而程序会分为R、D、F、Schema四个词,这个问题不大好办,因为S归属于前后不好区分,对比一下RDFschema就知道了。我想这已经不是词法和语法级别能处理得了,属于语义的范畴了。
可能使用中还会碰到其他的问题,我想如果再有其他特殊情况,我就准备彻底的做一个DFA来解决了,这个程序再打补丁可能比较困难了,时间上也许还不及DFA。
/**
* 分词,考虑了I.S.B.N问题
*
* @param source
* 待分的字符串
* @return String[]
*/
public String[] fenciWithISBN(String source) {
int positionOfDot;
StringBuffer tempSource = new StringBuffer(source);
while ((positionOfDot = tempSource.indexOf(".")) != -1) {
tempSource.deleteCharAt(positionOfDot);
}
source = tempSource.toString();
/* 分隔符的集合 */
String delimiters = " \t\n\r\f~!@#$%^&*()_+|`1234567890-=\\{}[]:\";'<>?,./'";
/* 根据分隔符分词 */
StringTokenizer stringTokenizer = new StringTokenizer(source,
delimiters);
Vector vector = new Vector();
/* 根据大写首字母分词 */
flag0: while (stringTokenizer.hasMoreTokens()) {
String token = stringTokenizer.nextToken();
/* 全大写的词不处理 */
boolean allUpperCase = true;
for (int i = 0; i < token.length(); i++) {
if (!Character.isUpperCase(token.charAt(i))) {
allUpperCase = false;
}
}
if (allUpperCase) {
vector.addElement(token);
continue flag0;
}
/* 非全大写的词 */
int index = 0;
flag1: while (index < token.length()) {
flag2: while (true) {
index++;
if ((index == token.length())
|| !Character.isLowerCase(token.charAt(index))) {
break flag2;
}
}
vector.addElement(token.substring(0, index));
token = token.substring(index);
index = 0;
continue flag1;
}
}
/*
* 复数转单数 参考以下文档:
* http://ftp.haie.edu.cn/Resource/GZ/GZYY/DCYFWF/NJSYYY/421b0061ZW_0015.htm
*/
for (int i = 0; i < vector.size(); i++) {
String token = (String) vector.elementAt(i);
if (token.equalsIgnoreCase("feet")) {
token = "foot";
} else if (token.equalsIgnoreCase("geese")) {
token = "goose";
} else if (token.equalsIgnoreCase("lice")) {
token = "louse";
} else if (token.equalsIgnoreCase("mice")) {
token = "mouse";
} else if (token.equalsIgnoreCase("teeth")) {
token = "tooth";
} else if (token.equalsIgnoreCase("oxen")) {
token = "ox";
} else if (token.equalsIgnoreCase("children")) {
token = "child";
} else if (token.endsWith("men")) {
token = token.substring(0, token.length() - 3) + "man";
} else if (token.endsWith("ies")) {
token = token.substring(0, token.length() - 3) + "y";
} else if (token.endsWith("ves")) {
if (token.equalsIgnoreCase("knives")
|| token.equalsIgnoreCase("wives")
|| token.equalsIgnoreCase("lives")) {
token = token.substring(0, token.length() - 3) + "fe";
} else {
token = token.substring(0, token.length() - 3) + "f";
}
} else if (token.endsWith("oes") || token.endsWith("ches")
|| token.endsWith("shes") || token.endsWith("ses")
|| token.endsWith("xes")) {
token = token.substring(0, token.length() - 2);
} else if (token.endsWith("s")) {
token = token.substring(0, token.length() - 1);
}
/* 处理完毕 */
vector.setElementAt(token, i);
}
/* 转为数组形式 */
String[] array = new String[vector.size()];
Enumeration enumeration = vector.elements();
int index = 0;
while (enumeration.hasMoreElements()) {
array[index] = (String) enumeration.nextElement();
index++;
}
/* 打印显示 */
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
/* 返回 */
return array;
}
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=415061
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -