亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? cjkknife.java

?? 對Lcuene的良好的封裝,提供了中文分詞字典 功能強大
?? JAVA
字號:
/**
 * Copyright 2007 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.paoding.analysis.knife;

import net.paoding.analysis.dictionary.Dictionary;
import net.paoding.analysis.dictionary.Hit;
import net.paoding.analysis.dictionary.Word;

/**
 * 
 * @author Zhiliang Wang [qieqie.wang@gmail.com]
 * 
 * @since 1.0
 * 
 */
public class CJKKnife implements Knife, DictionariesWare {

	// -------------------------------------------------

	private Dictionary vocabulary;
	private Dictionary noiseWords;
	private Dictionary noiseCharactors;
	private Dictionary units;

	// -------------------------------------------------

	public CJKKnife() {
	}

	public CJKKnife(Dictionaries dictionaries) {
		setDictionaries(dictionaries);
	}

	public void setDictionaries(Dictionaries dictionaries) {
		vocabulary = dictionaries.getVocabularyDictionary();
		noiseWords = dictionaries.getNoiseWordsDictionary();
		noiseCharactors = dictionaries.getNoiseCharactorsDictionary();
		units = dictionaries.getUnitsDictionary();
	}

	// -------------------------------------------------

	/**
	 * 分解以CJK字符開始的,后可帶阿拉伯數(shù)字、英文字母、橫線、下劃線的字符組成的語句
	 */
	public int assignable(Beef beef, int offset, int index) {
		char ch = beef.charAt(index);
		if (CharSet.isCjkUnifiedIdeographs(ch))
			return ASSIGNED;
		if (index > offset) {
			if (CharSet.isArabianNumber(ch) || CharSet.isLantingLetter(ch)
					|| ch == '-' || ch == '_') {
				return POINT;
			}
		}
		return LIMIT;
	}

	public int dissect(Collector collector, Beef beef, int offset) {
		// 當point == -1時表示本次分解沒有遇到POINT性質(zhì)的字符;
		// 如果point != -1,該值表示POINT性質(zhì)字符的開始位置,
		// 這個位置將被返回,下一個Knife將從point位置開始分詞
		int point = -1;

		// 記錄同質(zhì)字符分詞結(jié)束極限位置(不包括limit位置的字符)-也就是assignable方法遇到LIMIT性質(zhì)的字符的位置
		// 如果point==-1,limit將被返回,下一個Knife將從limit位置開始嘗試分詞
		int limit = offset + 1;

		// 構(gòu)建point和limit變量的值:
		// 往前直到遇到LIMIT字符;
		// 其中如果遇到第一次POINT字符,則會將它記錄為point
		GO_UNTIL_LIMIT: while (true) {
			switch (assignable(beef, offset, limit)) {
			case LIMIT:
				break GO_UNTIL_LIMIT;
			case POINT:
				if (point == -1) {
					point = limit;
				}
			}
			limit++;
		}

		// 如果從offset到beef.length()都是本次Knife的責任,則應讀入更多的未讀入字符,以支持一個詞分在兩次beef中的處理
		// 魔幻邏輯:
		// Beef承諾:如果以上GO_UNTIL_LIMIT循環(huán)最終把limit值設置為beef.length則表示還為未讀入字符。
		// 因為beef一定會在文本全部結(jié)束后加入一個char='\0'的值作為最后一個char標志結(jié)束。
		// 這樣以上的GO_UNTIL_LIMIT將在limit=beef.length()之前就已經(jīng)break,此時limit!=beef.length
		if (offset > 0 && limit == beef.length()) {
			return -offset;
		}

		// 記錄當前正在檢視(是否是詞典詞語)的字符串在beef中的始止位置(包含開始位置,不包含結(jié)束位置)
		int curSearchOffset = offset, curSearchEnd;

		// 記錄當前被檢視的字符串的長度,它的值恒等于(curSearchEnd - curSearchOffset)
		int curSearchLength;

		// 當前檢視的字符串的判斷結(jié)果
		Hit curSearch = null;

		// 限制要判斷的字符串的最大開始位置
		// 這個變量不隨著程序的運行而變化
		final int offsetLimit;
		if (point != -1)
			offsetLimit = point;
		else
			offsetLimit = limit;

		// 記錄到當前為止所分出的詞典詞語的最大結(jié)束位置
		int maxDicWordEnd = offset;

		// 記錄最近的不在詞典中的字符串(稱為孤立字符串)在beef的位置,-1表示沒有這個位置
		int isolatedOffset = -1;

		// 記錄到當前為止經(jīng)由詞典所切出詞的最大長度。
		// 用于輔助判斷是否調(diào)用shouldBeWord()方法,以把前后有如引號、書名號之類的,但還沒有被切出的字符串當成一個詞
		// 詳見本方法后面對maxDicWordLength的應用以及shouldBeWord()的實現(xiàn)
		int maxDicWordLength = 0;

		// 第1個循環(huán)定位被檢視字符串的開始位置
		// 被檢視的字符串開始位置的極限是offsetLimit,而非limit
		for (; curSearchOffset < offsetLimit; curSearchOffset++) {

			// 第二個循環(huán)定位被檢視字符串的結(jié)束位置(不包含該位置的字符)
			// 它的起始狀態(tài)是:被檢視的字符串一長度為1,即結(jié)束位置為開始位置+1
			curSearchEnd = curSearchOffset + 1;
			curSearchLength = 1;
			for (; curSearchEnd <= limit; curSearchEnd++, curSearchLength++) {

				// 通過詞匯表判斷,返回判斷結(jié)果curSearch
				curSearch = vocabulary.search(beef, curSearchOffset,
						curSearchLength);

				// ---------------分析返回的判斷結(jié)果--------------------------

				// 1)
				// 從詞匯表中找到了該詞語...
				if (curSearch.isHit()) {

					// 1.1)
					// 確認孤立字符串的結(jié)束位置=curSearchOffset,
					// 并調(diào)用子方法分解把從isolatedOffset開始的到curSearchOffset之間的孤立字符串
					// 孤立字符串分解完畢,將孤立字符串開始位置isolatedOffset清空
					if (isolatedOffset >= 0) {
						dissectIsolated(collector, beef, isolatedOffset,
								curSearchOffset);
						isolatedOffset = -1;
					}

					// 1.2)
					// 更新最大結(jié)束位置
					if (maxDicWordEnd < curSearchEnd) {
						maxDicWordEnd = curSearchEnd;
					}

					// 1.3)
					// 更新詞語最大長度變量的值
					if (curSearchOffset == offset
							&& maxDicWordLength < curSearchLength) {
						maxDicWordLength = curSearchLength;
					}
					
					// 1.2)
					// 通知collector本次找到的詞語
					Word word = curSearch.getWord();
					if (!word.isNoise()) {
						collector.collect(word.getText(), curSearchOffset,
							curSearchEnd);
					}
				}

				// 若isolatedFound==true,表示詞典沒有該詞語
				boolean isolatedFound = curSearch.isUndefined();

				// 若isolatedFound==false,則通過Hit的next屬性檢視詞典沒有beef的從offset到curWordEnd
				// + 1位置的詞
				// 這個判斷完全是為了減少一次詞典檢索而設計的,
				// 如果去掉這個if判斷,并不影響程序的正確性(但是會多一次詞典檢索)
				if (!isolatedFound && !curSearch.isHit()) {
					isolatedFound = curSearchEnd >= limit
							|| beef.charAt(curSearchEnd) < curSearch.getNext()
									.charAt(curSearchLength);
				}
				// 2)
				// 詞匯表中沒有該詞語,且沒有以該詞語開頭的詞匯...
				// -->將它記錄為孤立詞語
				if (isolatedFound) {
					if (isolatedOffset < 0 && curSearchOffset >= maxDicWordEnd) {
						isolatedOffset = curSearchOffset;
					}
					break;
				}

				// ^^^^^^^^^^^^^^^^^^分析返回的判斷結(jié)果^^^^^^^^^^^^^^^^^^^^^^^^
			} // end of the second for loop
		} // end of the first for loop

		// 上面循環(huán)分詞結(jié)束后,可能存在最后的幾個未能從詞典檢索成詞的孤立字符串,
		// 此時isolatedOffset不一定等于一個有效值(因為這些孤立字雖然不是詞語,但是詞典可能存在以它為開始的詞語,
		// 只要執(zhí)行到此才能知道這些雖然是前綴的字符串已經(jīng)沒有機會成為詞語了)
		// 所以不能通過isolatedOffset來判斷是否此時存在有孤立詞,判斷依據(jù)轉(zhuǎn)換為:
		// 最后一個詞典的詞的結(jié)束位置是否小于offsetLimit(!!offsetLimit, not Limit!!)
		if (maxDicWordEnd < offsetLimit) {
			dissectIsolated(collector, beef, maxDicWordEnd, offsetLimit);
		}

		// 現(xiàn)在是利用maxDicWordLength的時候了
		// 如果本次負責的所有字符串文本沒有作為一個詞被切分出(包括詞典切詞和孤立串切分),
		// 那如果它被shouldBeWord方法認定為應該作為一個詞切分,則將它切出來
		int len = limit - offset;
		if (len > 2 && len != maxDicWordLength
				&& shouldBeWord(beef, offset, limit)) {
			collector.collect(beef.subSequence(offset, limit).toString(),
					offset, limit);
		}

		// 按照point和limit的語義,返回下一個Knife開始切詞的開始位置
		return point == -1 ? limit : point;
	}

	// -------------------------------------------------

	/**
	 * 對孤立字符串分詞
	 * 
	 * @param cellector
	 * @param beef
	 * @param offset
	 * @param count
	 */
	protected void dissectIsolated(Collector collector, Beef beef, int offset,
			int limit) {
		int curSearchOffset = offset;
		int binOffset = curSearchOffset; // 進行一般二元分詞的開始位置
		int tempEnd;

		while (curSearchOffset < limit) {
			// 孤立字符串如果是漢字數(shù)字,比如"五十二萬","十三億",。。。
			tempEnd = collectNumber(collector, beef, curSearchOffset, limit,
					binOffset);
			if (tempEnd > curSearchOffset) {
				curSearchOffset = tempEnd;
				binOffset = tempEnd;
				continue;
			}

			// 魔幻邏輯:
			// noiseWords的詞在語言學上雖然也是詞,但CJKKnife不會把它當成詞匯表中的正常詞,
			// 有些noise詞可能沒有出現(xiàn)詞匯表,則就會被視為孤立字符串在此處理(不被視為詞匯、不進行二元分詞)
			tempEnd = skipNoiseWords(collector, beef, curSearchOffset, limit,
					binOffset);
			if (tempEnd > curSearchOffset) {
				curSearchOffset = tempEnd;
				binOffset = tempEnd;
				continue;
			}

			// 如果當前字符是noise單字,其不參加二元分詞
			Hit curSearch = noiseCharactors.search(beef, curSearchOffset, 1);
			if (curSearch.isHit()) {
				binDissect(collector, beef, binOffset, curSearchOffset);
				binOffset = ++curSearchOffset;
				continue;
			}
			curSearchOffset++;
		}

		// 
		if (limit > binOffset) {
			binDissect(collector, beef, binOffset, limit);
		}
	}

	protected int collectNumber(Collector collector, Beef beef, int offset,
			int limit, int binOffset) {

		// 當前嘗試判斷的字符的位置
		int curTail = offset;
		int number1 = -1;
		int number2 = -1;
		int bitValue = 0;
		int maxUnit = 0;
		boolean hasDigit = false;// 作用:去除沒有數(shù)字只有單位的漢字,如“萬”,“千”
		for (; curTail < limit
				&& (bitValue = CharSet.toNumber(beef.charAt(curTail))) >= 0; curTail++) {
			// 
			if (bitValue == 2
					&& (beef.charAt(curTail) == '兩'
							|| beef.charAt(curTail) == '倆' || beef
							.charAt(curTail) == '倆')) {
				if (curTail != offset) {
					break;
				}
			}
			// 處理連續(xù)漢字個位值的數(shù)字:"三四五六" ->"3456"
			if (bitValue >= 0 && bitValue < 10) {
				hasDigit = true;
				if (number2 < 0)
					number2 = bitValue;
				else {
					number2 *= 10;
					number2 += bitValue;
				}
			} else {
				if (number2 < 0) {
					if (number1 < 0) {
						number1 = 1;
					}
					number1 *= bitValue;
				} else {
					if (number1 < 0) {
						number1 = 0;
					}
					if (bitValue >= maxUnit) {
						number1 += number2;
						number1 *= bitValue;
						maxUnit = bitValue;
					} else {
						number1 += number2 * bitValue;
					}
				}
				number2 = -1;
			}
		}
		if (!hasDigit) {
			return offset;
		}
		if (number2 > 0) {
			if (number1 < 0) {
				number1 = number2;
			} else {
				number1 += number2;
			}
		}
		if (number1 >= 0) {
			// 二元分詞先
			if (offset > binOffset) {
				binDissect(collector, beef, binOffset, offset);
			}
			collector.collect(String.valueOf(number1), offset, curTail);
			
			if (units != null) {
				// 后面可能跟了計量單位
				Hit wd = null;
				Hit wd2 = null;
				int i = curTail + 1;
				while ((wd = units.search(beef, curTail, i - curTail)).isHit()) {
					wd2 = wd;
					i ++;
					if (!wd.isUnclosed()) {
						break;
					}
				}
				i --;
				if (wd2 != null) {
					collector.collect(wd2.getWord().getText(), curTail, i);
					return i;
				}
			}
		}

		// 返回最后一個判斷失敗字符的結(jié)束位置:
		// 該位置要么是offset,要么表示curTail之前的字符(不包括curTail字符)已經(jīng)被認為是漢字數(shù)字
		return curTail;
	}

	protected int skipNoiseWords(Collector collector, Beef beef, int offset,
			int end, int binOffset) {
		Hit word;
		for (int k = offset + 2; k <= end; k++) {
			word = noiseWords.search(beef, offset, k - offset);
			if (word.isHit()) {
				// 二元分詞
				if (binOffset > 0 && offset > binOffset) {
					binDissect(collector, beef, binOffset, offset);
					binOffset = -1;
				}
				offset = k;
			}
			if (word.isUndefined() || !word.isUnclosed()) {
				break;
			}
		}
		return offset;
	}

	protected void binDissect(Collector collector, Beef beef, int offset,
			int limit) {
		// 二元分詞之策略:以W、X、Y、Z表示孤立字符串中的4個漢字
		// X ->X 單個字的孤立字符串作為一個詞
		// XY ->XY 只有兩個字的孤立字符串作為一個詞
		// XYZ ->XY/YZ 多個字(>=3)的孤立字符串"兩兩組合"作為一個詞
		// WXYZ ->WX/XY/YZ 同上

		if (limit - offset == 1) {
			collector.collect(beef.subSequence(offset, limit).toString(),
					offset, limit);
		} else {
			// 窮盡二元分詞
			for (int curOffset = offset; curOffset < limit - 1; curOffset++) {
				collector.collect(beef.subSequence(curOffset, curOffset + 2)
						.toString(), curOffset, curOffset + 2);
			}
		}
	}

	protected boolean shouldBeWord(Beef beef, int offset, int end) {
		char prevChar = beef.charAt(offset - 1);
		char endChar = beef.charAt(end);
		// 中文單雙引號
		if (prevChar == '“' && endChar == '”') {
			return true;
		} else if (prevChar == '‘' && endChar == '’') {
			return true;
		}
		// 英文單雙引號
		else if (prevChar == '\'' && endChar == '\'') {
			return true;
		} else if (prevChar == '\"' && endChar == '\"') {
			return true;
		}
		// 中文書名號
		else if (prevChar == '《' && endChar == '》') {
			return true;
		} else if (prevChar == '〈' && endChar == '〉') {
			return true;
		}
		// 英文尖括號
		else if (prevChar == '<' && endChar == '>') {
			return true;
		}
		return false;
	}

}

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
欧美成人性战久久| 日本免费在线视频不卡一不卡二| 亚洲六月丁香色婷婷综合久久| 视频在线在亚洲| 99久久99久久精品免费观看| 日韩视频一区二区三区在线播放 | 成人精品高清在线| 欧美日韩精品系列| 综合亚洲深深色噜噜狠狠网站| 久久99热国产| 欧美精品免费视频| 亚洲激情自拍偷拍| 99视频精品在线| 久久综合九色综合97婷婷女人| 亚洲不卡一区二区三区| 99久久777色| 国产精品人人做人人爽人人添| 蜜桃精品视频在线| 91麻豆精品国产91| 亚洲一区在线观看免费观看电影高清| 成人一区二区三区中文字幕| 久久先锋影音av鲁色资源| 奇米色一区二区| 91精品国产欧美日韩| 亚洲国产日韩在线一区模特| 91亚洲永久精品| 亚洲三级电影网站| 99精品久久久久久| 国产精品久久久久久久久久免费看| 国产自产视频一区二区三区| 欧美www视频| 国产一区二区91| 国产丝袜美腿一区二区三区| 国产综合久久久久影院| 久久综合狠狠综合| 国产一区二区在线视频| 日本一区二区三区dvd视频在线| 国产在线播放一区| 国产欧美精品一区aⅴ影院| 国产精品资源在线看| 欧美激情一区二区三区四区| 99精品欧美一区二区三区小说| 综合久久给合久久狠狠狠97色| 99视频精品在线| 亚洲精选视频免费看| 欧美日韩日本视频| 久久se精品一区精品二区| 日韩亚洲电影在线| 国产精品888| 亚洲精品老司机| 欧美久久免费观看| 九九九久久久精品| 中文字幕亚洲成人| 欧美日韩精品欧美日韩精品一综合| 男人的j进女人的j一区| 久久精品免费在线观看| 91影院在线观看| 首页综合国产亚洲丝袜| 久久久久久99久久久精品网站| 成人综合激情网| 亚洲综合久久久久| 欧美精品一区男女天堂| 成人av电影在线播放| 亚洲成av人片一区二区三区| 26uuu国产一区二区三区| 91一区二区在线| 免费看精品久久片| 亚洲人妖av一区二区| 日韩欧美国产午夜精品| 成人国产精品免费网站| 婷婷综合在线观看| 国产精品久久毛片| 欧美精品久久久久久久多人混战| 国产成人免费视频一区| 亚洲第一二三四区| 国产精品免费视频观看| 欧美刺激脚交jootjob| 99久久久久免费精品国产| 日韩电影在线一区二区三区| 国产精品素人视频| 日韩亚洲欧美中文三级| 色一情一伦一子一伦一区| 国产一区999| 亚洲bt欧美bt精品777| 国产精品久久久久四虎| 精品日韩av一区二区| 欧美日韩一区二区三区四区| 大尺度一区二区| 老汉av免费一区二区三区 | 免费在线观看视频一区| 最新国产成人在线观看| 久久综合久色欧美综合狠狠| 在线观看91精品国产麻豆| 99精品视频在线观看免费| 国产乱人伦偷精品视频不卡 | 欧美乱熟臀69xxxxxx| 99久久精品国产麻豆演员表| 国产精品99久| 精品一区二区精品| 亚洲成人福利片| 亚洲黄色av一区| 中文字幕字幕中文在线中不卡视频| 精品国产精品一区二区夜夜嗨| 欧美日韩一区 二区 三区 久久精品| av在线不卡观看免费观看| 国产精品99精品久久免费| 韩国午夜理伦三级不卡影院| 日韩高清国产一区在线| 日韩影视精彩在线| 日本不卡一区二区三区高清视频| 亚洲成人av一区二区三区| 亚洲午夜久久久久久久久电影网| 亚洲免费观看视频| 亚洲精品老司机| 亚洲国产精品久久久久婷婷884 | 国产在线播精品第三| 精品亚洲国产成人av制服丝袜| 美女爽到高潮91| 精品一区二区三区免费毛片爱| 久久99九九99精品| 国产自产2019最新不卡| 国产一二精品视频| 国产99久久久国产精品| av电影天堂一区二区在线观看| 成人sese在线| 91亚洲精品久久久蜜桃网站 | 一区二区三区美女视频| 亚洲国产毛片aaaaa无费看| 亚洲国产日韩av| 男男视频亚洲欧美| 国产精品亚洲一区二区三区在线| 国产精品影视天天线| 成人福利视频在线| 欧美视频在线不卡| 精品日韩欧美一区二区| 国产精品家庭影院| 亚洲一区二区四区蜜桃| 日本成人在线一区| 国产suv一区二区三区88区| eeuss鲁片一区二区三区| 欧美日韩国产影片| www国产成人免费观看视频 深夜成人网 | 成人免费电影视频| 色噜噜狠狠一区二区三区果冻| 在线观看亚洲a| 精品成人一区二区三区| 专区另类欧美日韩| 日本不卡视频在线| 粉嫩av亚洲一区二区图片| 在线视频综合导航| 精品国产不卡一区二区三区| 中文字幕综合网| 蜜臀av亚洲一区中文字幕| av亚洲精华国产精华精| 欧美精品久久一区二区三区| 中文字幕第一区综合| 亚洲一二三区不卡| 国产裸体歌舞团一区二区| 在线亚洲精品福利网址导航| 久久综合狠狠综合久久激情| 亚洲精品国产视频| 国产成人av一区| 在线不卡a资源高清| 国产精品色哟哟网站| 奇米色777欧美一区二区| 色呦呦一区二区三区| 久久久国产精品麻豆| 日韩精品电影一区亚洲| 91麻豆精品秘密| 久久欧美一区二区| 免费xxxx性欧美18vr| 色婷婷综合久久久中文字幕| 久久精品一级爱片| 日韩电影在线看| 欧美主播一区二区三区| 国产精品国产馆在线真实露脸| 九九久久精品视频| 日韩一级二级三级| 首页欧美精品中文字幕| 在线观看日韩一区| 国产精品麻豆欧美日韩ww| 激情欧美一区二区三区在线观看| 欧美精品九九99久久| 亚洲午夜精品久久久久久久久| 99精品黄色片免费大全| 国产精品免费久久久久| 国产精品自产自拍| 久久一区二区视频| 久久99久久99精品免视看婷婷 | 亚州成人在线电影| 欧美在线|欧美| 亚洲综合999| 欧日韩精品视频| 亚洲激情综合网| 在线观看亚洲一区| 一区二区三国产精华液| 91麻豆精品视频| 亚洲美女视频一区| 色综合天天综合| 亚洲欧美一区二区不卡|