Java實現(xiàn)的最大匹配分詞算法詳解
本文實例講述了Java實現(xiàn)的最大匹配分詞算法。分享給大家供大家參考,具體如下:
全文檢索有兩個重要的過程:
1分詞
2倒排索引
我們先看分詞算法
目前對中文分詞有兩個方向,其中一個是利用概率的思想對文章分詞。 也就是如果兩個字,一起出現(xiàn)的頻率很高的話,我們可以假設(shè)這兩個字是一個詞。這里可以用一個公式衡量:M(A,B)=P(AB)/P(A)P(B),其中 A表示一個字,B表示一個字,P(AB)表示AB相鄰出現(xiàn)的概率,P(A)表示A在這篇文章中的頻度,P(B)表示B在這篇文章中的頻度。用概率分詞的好 處是不需要借助詞典的幫助,壞處是算法比較麻煩,效率不高,也存在一定的出錯率。
另外的一個方向是使用詞典分詞。就是事先為程序準備一個詞典,然后通過這個詞典對文章分詞。目前較流行的方式有正向最大匹配算法和逆向最大匹配算法。逆向最大匹配算法在準確性上要更好一些。
以 “我是一個壞人” 為例,并最大詞長為3,詞庫包含有 我、是、一、個、一個、壞人、大壞人
正向的順序為
我是一
我是
我 ===> 得到一個詞
是一個
是一
是 ===>得到一個詞
一個壞
一個===> 得到一個詞
壞人===>得到一個詞
結(jié)果 我、是、一個、壞人
反向算法
個壞人
壞人==> 壞人
是一個
一個==> 一個
我是
是==> 是
我==> 我
結(jié)果 我、是、一個、壞人
java代碼如下
package data;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* 最大匹配分詞算法
*
* @author JYC506
*
*/
public class SplitString {
private Set<String> set = new HashSet<String>();
private int positiveOver = 0;
private int reverseOver = 0;
/**
* 正向最大匹配
*
* @param str 要分詞的句子
* @param num 詞的最大長度
* @return
*/
public String[] positiveSplit(String str, int maxSize) {
int tem = 0;
int length = str.length();
String[] ss = new String[length];
char[] cc = str.toCharArray();
for (int i = 0; i < length; i++) {
positiveOver = 0;
String sb = this.toStr(cc, i, maxSize);
ss[tem++] = sb;
i = i + positiveOver;
}
String[] ss2 = new String[tem];
System.arraycopy(ss, 0, ss2, 0, tem);
return ss2;
}
/**
* 添加詞庫
*
* @param words
*/
public void addWord(String[] words) {
for (String st : words) {
this.set.add(st);
}
}
/**
* 逆向最大匹配
*
* @param str
* @param num
* @return
*/
public String[] reverseSplit(String str, int num) {
int tem = 0;
int length = str.length();
String[] ss = new String[length];
char[] cc = str.toCharArray();
for (int i = str.length() - 1; i > -1; i--) {
reverseOver = 0;
String sb = this.toStr2(cc, i, num);
tem++;
ss[--length] = sb;
i = i - reverseOver;
}
String[] ss2 = new String[tem];
System.arraycopy(ss, str.length() - tem, ss2, 0, tem);
return ss2;
}
private String toStr(char[] cs, int start, int num) {
int num2 = num;
out: for (int j = 0; j < num; j++) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < num2; i++) {
if (start + i < cs.length) {
sb.append(cs[start + i]);
} else {
num2--;
j--;
continue out;
}
}
if (set.contains(sb.toString())) {
positiveOver = num2 - 1;
return sb.toString();
}
num2--;
}
return String.valueOf(cs[start]);
}
private String toStr2(char[] cs, int start, int num) {
int num2 = num;
for (int j = 0; j < num; j++) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < num2; i++) {
int index = start - num2 + i + 1;
if (index > -1) {
sb.append(cs[index]);
} else {
num2--;
}
}
if (set.contains(sb.toString())) {
reverseOver = num2 - 1;
return sb.toString();
}
num2--;
}
return String.valueOf(cs[start]);
}
public static void main(String[] args) {
String[] words = new String[] { "我們", "我們五人", "五人一組", "一組" };
SplitString ss = new SplitString();
/*添加詞到詞庫*/
ss.addWord(words);
String st = "我們五人一組";
System.out.println("腳本之家測試結(jié)果:");
System.out.println("要分詞的句子:" + st);
/*使用兩種方式分詞,下面我指定最大詞長度為4*/
String[] ss2 = ss.reverseSplit(st, 4);
String[] ss1 = ss.positiveSplit(st, 4);
System.out.println("正向最大匹配分詞算法分詞結(jié)果:" + Arrays.toString(ss1));
System.out.println("逆向最大匹配分詞算法分詞結(jié)果:" + Arrays.toString(ss2));
}
}

更多關(guān)于java算法相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java字符與字符串操作技巧總結(jié)》、《Java操作DOM節(jié)點技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設(shè)計有所幫助。
相關(guān)文章
一文搞懂spring boot本地事務(wù)@Transactional參數(shù)
這篇文章主要介紹了spring boot本地事務(wù)@Transactional參數(shù)詳解,本文通過示例代碼圖文相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-10-10
Springboot工具類FileCopyUtils使用教程
這篇文章主要介紹了Springboot內(nèi)置的工具類之FileCopyUtils的使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-12-12

