//------------------------------------------------------- // 分割なし完全一致の語 static public WordTable Scan(WordChain wChain, WordTable wTable) { if (wTable.IsTranslated()) { return(wTable); // 変換済みなら何もしない } // 翻訳しなくていい文字は抜ける if (!wTable.IsWord() || // 空白や制御文字 wTable.IsDigit() || wTable.IsOther()) // 記号 { return(wTable); } // 助詞なら抜ける if (wTable.posCategory == PosCategory.PP) { return(wTable); } // 独立した1文字の語は辞書より先に検索 (単独の이など) if (wTable.word.Length == 1) { CheckOneWord(wTable); if (wTable.transWord != "") { return(wTable); // match } } // 全体で完全一致で検索 SearchResult sResult = KJ_dict.SearchFull(wTable.word); if (sResult != null) { wTable.SetResult(sResult); return(wTable); // 完全一致で見つかった } // 4文字語の調査 (部分分割後は使わない) WordChain wc = Check4Chars(wTable); if (wc != null) { wChain.Swap(wTable, wc); return(wc.Tail); } return(wTable); }
//------------------------------------------------------- // 語のchainを先頭から舐め、助詞(Postpositional Particle)を分解する。 static private WordTable ScanPPJp(WordChain wChain, WordTable wTable) { // 語を舐め、助詞を分解する。 if (wTable.IsTranslated() || wTable.IsDigit()) { // 翻訳済み または 数字ならなにもしない。 return(wTable); } // J-->K方向の場合、ハングルは // 前の語に依存するので訳語(ハングル)の設定は別途。 // 助詞である事の確定だけ試みる // 分離されたひらがなの助詞判定だけ PosCategory pp = CheckPos_Hira(wTable.word); if (PosCategory.PP == pp) { wTable.posCategory = pp; } // 漢字+ひらがなの形での助詞分離 if (wTable.charCategory == CharCategory.KanHira) { WordChain resultChain = DivideJapanesePP(wTable); if (resultChain != null) { wChain.Swap(wTable, resultChain); // 前の語は未翻訳なのでそれを返す wTable = resultChain.Head; } } return(wTable); }
//------------------------------------------------------- // 語のchainを先頭から舐め、助数詞・冠数詞を解析する。 static public WordTable Scan(WordChain wChain, WordTable wTable) { if (wTable.IsTranslated()) { return(wTable); // 変換済みなら何もしない } WordTable next = wTable.NextWord(); // 次の有効な語を返す。(空白skip) // 前後を数字(Digit)に挟まれる場合 if ((wTable.prev != null && wTable.prev.IsDigit()) && (next != null && next.IsDigit())) { string transword = KJ_Filter.SearchNumConnecting(wTable.word); if (transword != "") { wTable.transWord = transword; wTable.posCategory = PosCategory.Numerative; wTable.Cost = 1; return(wTable); } } // 1つ前のWordTableは数字(Digit)の場合 // または数詞(Numeral)である場合 if ((wTable.prev != null && wTable.prev.IsDigit()) || // 800억 の 억 (wTable.PrevWord() != null && wTable.PrevWord().posCategory == PosCategory.Numeral) // 800억원 --> 800+억+원の원 // 160억 개의 のように空白をはさむ事があるので空白skipで前の語を調べる ) { WordChain dividedChain = DivideCountable(wTable); if (dividedChain != null) { // 助数詞であった // devidedChainは 助数詞+語のチェーン。wTableと入れ替える // (+語はない場合もある) wChain.Swap(wTable, dividedChain); // 処理済みTable変更 wTable = dividedChain.Head; } } else { // 次の語が数字である場合 (冠数詞) NumerativePrefix // ★前数字と違い、空白はさんでも許す (약 90만 or 약90만) if (next != null && next.IsDigit()) { string transword = KJ_Filter.SearchPreNum(wTable.word); // string transword = CheckPreNum(wTable); if (transword != "") { wTable.transWord = transword; wTable.posCategory = PosCategory.NumerativePrefix; // ちょっと違うか。あとで wTable.Cost = 1; } } } return(wTable); }
//-------------------------------------------------------------------- // 語の変換 (語の分解あり) // 語分解で翻訳済み末尾がずれることがあるのでWordTableを返す // ABCDEF という語に対し、 // ABCDE + F // ABCD + EF // ABC + DEF // : : // と調べていき、最小コストの訳語がとれる分割を採用する // static public WordChain WordPartProc(WordTable wt) { SearchResult sResult; String str = wt.word; if (wt == null) { return(null); } if (wt.word != null && wt.word.Length == 1) // 1文字検索はしない { return(null); } if (wt.IsTranslated() || wt.IsDigit()) { return(null); // 翻訳済みまたは 数字なら 何もしない } #if DEBUG_LOG KJ_Analyzer.WriteDebugLog("WordPartProc:" + wt.word); #endif // 再起に備え,まず完全一致で検索 sResult = KJ_dict.SearchFull(str); if (sResult != null) { wt.SetResult(sResult); // 全体でmatch WordChain wc = new WordChain(wt); return(wc); } // 部分語の2文字は分割しない if (wt.word != null && wt.word.Length == 2 && wt.divided != Divided.Non) { return(null); } // 3文字の「ハングルまたは漢字」なら特別チェック if (wt.word != null && wt.word.Length == 3 && wt.divided != Divided.Non && // 部分語の3文字語は除外 (CodeCheck.IsHangul(wt.word) || CodeCheck.IsKanji(wt.word)) ) { WordChain wc3 = Check3Chars(wt); if (wc3 != null) { return(wc3); } } // int target_len=2; // 2005.09.03 やっぱり1文字まで切らないとだめだ int target_len = 1; int str_len = str.Length; int minimumCost = 9999; WordChain minimumCostChain = null; // 前から1文字ずつ落としつつ,検索。 while (true) { int start = str_len - target_len; // if( start <= 1 ){ // 2005.09.03 if (start <= 0) { break; } // 文字列を分割する // str --> str2 + str3 // String str2 = str.Remove (start, target_len ); // String str3 = str.Substring(start, target_len ); // 前から分割に変えた(2005.08) String str2 = str.Remove(target_len, start); String str3 = str.Substring(target_len, start); //あとできれいに // 前と後ろを、それぞれ検索 WordChain wc2 = DividedWordSearch(str2); WordChain wc3 = DividedWordSearch(str3); #if DEBUG_LOG KJ_Analyzer.WriteDebugLog("str2/str3:" + str2 + "/" + str3); #endif WordTable wt2, wt3; if (wc2 == null) { wt2 = new WordTable(str2); wc2 = new WordChain(wt2); } if (wc3 == null) { wt3 = new WordTable(str3); wc3 = new WordChain(wt3); } // 分割情報設定 if (wt.divided == Divided.Non) { wc2.Head.divided = Divided.Lead; wc3.Head.divided = Divided.Trail; } if (wt.divided == Divided.Lead) { wc2.Head.divided = Divided.Lead; wc3.Head.divided = Divided.Middle; } if (wt.divided == Divided.Middle) { wc2.Head.divided = Divided.Middle; wc3.Head.divided = Divided.Middle; } if (wt.divided == Divided.Trail) { wc2.Head.divided = Divided.Middle; wc3.Head.divided = Divided.Trail; } // wc2とwc3をつなぐ wc2.Add(wc3); // wc2---wc3 のコストを計算 int divChainCost = wc2.GetChainCost(); if (minimumCost >= divChainCost) { minimumCostChain = wc2; minimumCost = divChainCost; //最小コストの更新 } #if DEBUG_LOG KJ_Analyzer.WriteDebugLog("wc2:" + wc2.Head.word + "," + wc2.Head.Cost); KJ_Analyzer.WriteDebugLog("wc3:" + wc3.Head.word + "," + wc3.Head.Cost); KJ_Analyzer.WriteDebugLog("divChainCost:" + divChainCost); #endif target_len++; } // end of while // Chain中のwordが全て翻訳できていない if (minimumCostChain == null || (minimumCostChain != null && !minimumCostChain.IsTranslated())) { return(null); } // 翻訳できていない部分chainを再起実行 WordTable subT = minimumCostChain.Head; while (subT != null) { if (!subT.IsTranslated()) { WordChain subWc = WordPartProc(subT); if (subWc != null) { WordTable wNext = subT.next; minimumCostChain.Swap(subT, subWc); subT = wNext; continue; } } subT = subT.next; } return(minimumCostChain); }