この記事では、Javaによって実装された双方向マッチングワードセグメンテーションアルゴリズムについて説明します。次のように、参照のために共有してください。
いくつかの一般的な単語セグメンテーションアルゴリズムは次のとおりです。文字列マッチングに基づく単語セグメンテーション方法、理解に基づく単語セグメンテーション方法、および統計に基づく単語セグメンテーション方法。この記事では、文字列マッチング方法を使用しています。
フォワードマッチング分詞:
このアルゴリズムは、文字列の左側からセグメンテーションマッチングを実行するWord分詞辞書に基づいて実装されます。辞書が存在する場合、分割された単語を返し、前の文字列から単語をカットし、ループして文字列サイズが0になるまでカットします。
たとえば、STR = "私たちはすべて、北西A&F大学情報工学部の生徒です。」
1。分詞の長さlen = maxという単語を定義し、左からlen文字を取り出します= "私たちはすべて北西農業と林業です」と辞書の単語を一致させます。
2.辞書にそのような単語がない場合は、最後の文字を削除して単語に割り当て、レン値は1だけ削減されます。
3.辞書またはlen = 1に単語が見つかるまでステップ2を繰り返し、ループを終了します。
4. STRから分割された単語を切り取り、STRが分解されるまで手順1、2、および3を繰り返します。
逆最大一致分詞:
フォワードワードセグメンテーションアルゴリズムのように、文字列の長さが0になるまで、文字列の右側から始まります。ここでは詳細にはなりません。
双方向マッチング分詞:
この方法は、順方向分詞と逆分詞に基づいてあいまいさをセグメント化するためのあいまいさ分詞を作成することです。 「ヘビを食べるアルゴリズム」の実装を提案します。単語セグメンテーションを実行するための文字列は食べ物です。 2つの食いしん坊なヘビがあり、1つは左から右に食べます。他の人は右から左に食べます。左右の分詞の結果が曖昧である限り、2つのヘビがそれを噛みます。ヘビが食べる弦は分詞になります。左と右の分詞の間に常に曖昧さがある場合、2つのヘビは食べ続けます。 2つのヘビが弦の間で交差するとき、間違いなく曖昧さはありません。この時点で、左側の貪欲なヘビの腹の分詞は、真ん中には曖昧さがなく、右側の貪欲なヘビの腹の分詞があり、そのうち3つが最終分詞です。
この記事は、段落全体を言葉に分割することです。最初に、段落は句読点に基づいた文に分割され、次に各文が出力されて単語を分割します。
パッケージcn.nwsuaf.spilt; import java.io.bufferedreader; import java.io.filereader; import java.io.ioexception; import java.util.arraylist; import java.util.hashmap; import java.util.list; Import java.util.util.map;前方および逆方向の最大マッチングワードセグメンテーションアルゴリズム* @author liu yonglang**/public class wordspilt {/***ストレージワードセグメンテーション辞書*/private map <string、integer> map = new hashmap <string、integer>(); / ***最大の単語カット長は5つの漢字です*/ private int max_length = 5; /** *構築方法の単語分詞辞書を読み、それをマップに保存 * * * @Throws IOException */public wordspilt()throws ioexception {bufferedreader br = new filereader( "src/dict.txt"));文字列line = null; while((line = br.readline())!= null){line = line.trim(); map.put(line、0); } br.close(); } / ***最大ワードカット長を設定** @param max*最大ワードカット長* / public void setMaxLength(int max){this.max_length = max; } / ** *現在の最大ワードカット長を取得します。デフォルトは5(5漢文字) * * @return現在の最大ワードカット長 * / public int getMaxLength(){return this.max_length; } / ** *最大マッチングワードカットアルゴリズム * * @param spiltStr * string to split * @param lefttoright *スライス方向、trueは左から右に、falseは右から左へ、falseは * @return * / public <文字列>流出(文字列spiltstr、boolean lefttoright){ / / spiltStr.isの場合は空の場合(ヌル; //肯定的な一致するスプリット文字列リスト<string> leftwords = new ArrayList <String>()を保存します。 //ネガティブマッチングスプリット文字列リスト<String> rightWords = new ArrayList <String>()を保存します。 // string word = nullのスライスの文字列; //単語の長さを取り、最大値に初期化int wordlength = max_length; // string int position = 0の現在の位置にあります。 //文字列の長さは処理されていますint length = 0; //文字列の追加スペースを削除spiltstr = spiltstr.trim()。置換( "// s+"、 ""); //スライスする文字列がスライスされていない場合、ループセグメンテーション(長さ<spiltstr.length()){//スライスされていない文字列の長さが最大値よりも低い場合、単語自体の長さに等しい場合、spiltstr.length() - 長さ<max_length)wordstr.length = spiltStr.length() //それ以外の場合は、デフォルト値を取得します。 //それが前方の最大一致の場合、SpiltStrの位置からの切断を開始します(lefttoright){position = length; word = spiltstr.substring(位置、位置 + wordlength); } //逆最大一致の場合、spiltstrの端から切断を開始します{position = spiltstr.length() - length; word = spiltstr.substring(position -wordlength、position); } //現在の位置から指定された長さの文字列を開始します//単語分詞辞書に文字列が切断されていない場合、文字を破棄しますwhile(!map.containskey(word)){//単一の単語の場合、loopをexit if(word.length()== 1){//文字または番号の場合、連続文字または数字を一緒に分割しますループして後続の連続文字を合計するif(refttoright){for(int i = spiltstr.indexof(word、position)+1; i <spiltstr .length(); i ++){if((i)> = '0' && spiltstr.charat(i)<= '> ='> | '' ' .charat(i)<= 'z')|| } else break; }} else {//逆一致の場合、(int i = spiltstr.indexof(word、position -1)-1; i> = 0; i-)の現在の位置の前に連続数とアルファベット順の文字を加算してフリップします。 'A' && spiltstr.charat(i)<= 'z')|| if(i == 0){stringbuffer sb = new StringBuffer(word); word = sb.Reverse()。toString(); }} else {// flip operation stringbuffer sb = new stringbuffer(word); word = sb.Reverse()。toString();壊す; } } } } 壊す; } //それが前方の最大一致の場合、(lefttoright)word = word.substring(0、word.length() - 1); //それ以外の場合は、最初の文字を破棄しますelse word = word.substring(1); } // split文字列を指定されたテーブルに保存します(lefttoright)leftwords.add(word); else rightwords.add(word); //処理された文字列を追加する長さ += word.length(); } //逆の最大一致の場合、テーブルの文字列を調整して(!lefttoright){for(int i = rightwords.size() - 1; i> = 0; i--){lefwords.add(rightwords.get(i)); }} //スライス結果を返す左ワードを返します。 } / ** * 2つのセットが等しいかどうかを判断します * * @param list1 * set 1 * @param list2 * set 2 * @return return true if if equal、それはfalse * / public boolean isequal(list <string> list <string> list2){if(list1.isempty()&& list2.isempty()return fals; if(list1.size()!= list2.size())return false; for(int i = 0; i <list1.size(); i ++){if(!list1.get(i).equals(list2.get(i)))return false; } trueを返します。 } / ***判別分詞のあいまいさ機能** @param inputstr* string to vided* @returnパーティション結果* / publicリスト<string> resultword(string inputstr){//パーティション結果<文字列> result = new arraylist <string>(); // "left snake"分詞結果リスト<string> resultleft = new arrayList <String>(); // "Medium Snake"(Divergent Part)分詞結果リスト<String> resultMiddle = new ArrayList <String>(); // "right snake"分詞結果リスト<string> resultright = new ArrayList <String>(); //フォワード最大マッチングワードセグメンテーション結果<文字列>左= new ArrayList <String>(); //逆最大一致ワードセグメンテーション結果<string> right = new arrayList <String>();左=こぼれた(inputstr、true); /*system.out.println("forward分詞result: "); for(string string:left){system.out.print(string + "/"); } system.out.println( "/n逆分詞result:"); */ right = spilled(inputstr、false); /*for(string string:right){system.out.print(string + "/"); } system.out.println( "/ nboth-word word分詞result:");*/ // //両端の単語分詞スプライシングが入力文字列の中央に交差しているかどうかを判断します。交差点がない限り、それはループを続けます(left.get(0).length() + right.get(right.size() - 1).length()<inputstr .length()){//前方ワードの結果と逆の結果の結果が等しい場合、フォワード結果はループ(equal = rift){restmid of oftion = mid = midber = eftion壊す; } //フォワードワード分詞と逆分詞の結果が異なる場合、分詞の数が少なくなり、(reft.size()!= right.size()){resultmiddle = left.size()<reagt.size()?左:右;壊す; } //上記の条件が満たされていない場合は、「ヘビ」アルゴリズムを実装します。 //「右貪欲なヘビ」の最後の単語を食べます分詞resultright.add(right.get(right.size() - 1)); //「snake」で食べられる単語を削除しますinputstr = inputstr.substring(left.get(0).length()); inputstr = inputstr.substring(0、inputstr.length() - right.get(right.size() - 1).length()); //干渉が残っているのを防ぐために、以前の正と逆ワードのセグメンテーションの結果をクリーンアップします。clear(); right.clear(); //左=こぼれた列の分詞を起動します(inputstr、true);右=こぼれた(inputstr、false); } //ループの端は、分詞があいまいではないか、「貪欲なヘビ」が交差点で単語分詞である場合、両端から交差点に食べることを意味します。 (left.get(0).length() + right.get(right.size() - 1).length()> inputstr .length())resultmiddle = left; //中央の交差点が交差する場合、それは食べ物を取ります、そしてそれは単に重複していません://前方方向の最初の分詞 +逆方向の最後の分詞の長さ=文字列の全長を入力すると、順方向と逆方向を綴ることができます。 resultmiddle.add(left.get(0)); resultmiddle.add(right.get(right.size() - 1)); } //(string string:resultLeft){result.add(string)の最終結果に明確な分詞結果を追加する; } for(string string:resultmiddle){result.add(string); } //「正しい貪欲なヘビ」に保存されている分詞は、(int i = resultright.size() - 1; i> = 0; i-)に対して転送するように調整する必要があります。 } return result; } / ** *段落をいくつかの文に分割し、単語セグメンテーションを個別に実行します * * @param inputstr *この段落の@return分詞結果 * / public list <string> resultspilt(string inputstr){//最終的な単語セグメンテーション結果<<文字列> result <文字列> //句読点が発生した場合、それはいくつかの文に分割されますstring regex = "[、。;!?]"; string [] st = inputstr.split(regex); //各文の分詞結果を(string stri:st){list <string> list = resultword(stri)の最終分詞結果に追加します。 result.addall(list); } return result; } public static void main(string [] args){//例:住宅価格が高価かどうかを確認してください。 Table Tennis Auction Scanner input = new Scanner(system.in); string str = input.nextline(); wordspilt wordspilt = null; try {wordspilt = new wordspilt(); } catch(ioexception e){e.printstacktrace(); } list <string> list = wordspilt.resultword(str); for(string string:list){system.out.print(string + "/"); }}}src/dict.txtは辞書ファイルであり、設定は次のとおりです。
wulin.comスクリプトのダウンロードスクリプトチュートリアル素材のダウンロードへようこそ
操作結果は次のとおりです。
Javaアルゴリズムの詳細については、このサイトに興味のある読者は、「Javaデータ構造とアルゴリズムのチュートリアル」、「Java操作DOMノードのヒントの要約」、「Javaファイルの要約およびディレクトリ操作のヒント」、「Java Cache操作のヒントの要約」というトピックを見ることができます。
この記事がみんなのJavaプログラミングに役立つことを願っています。