IK 분사 소스 분석 연재 (二) -- 서브 분사 기

전재 출처 를 밝 혀 주 십시오:
http://blog.chinaunix.net/uid-20761674-id-3424176.html
 
제1 편
IK 분사 소스 코드 분석 연재 (一) -- 메 인 프로 세 스
 
IK 분사 의 주요 절차 와 기능 을 개요 적 으로 설명 하 였 으 며, 세부 적 인 부분 에 들 어가 야 합 니 다. 이번 에는 IK 의 세 개의 분사 기 를 상세 하 게 소개 합 니 다: CJKSegmenter (중국어 분사), CNQuantifierSegmenter (수량 어 분사), LetterSegmenter (자모 분사).
이 세 개의 단어 기 는 코드 가 매우 유사 합 니 다. 사고방식 은 모두 같 습 니 다. 사전 트 리 (CJK 사용) 나 다른 간단 한 데이터 구조 (CN Quantifier Segmenter 와 Letter Segmenter) 를 사용 하여 텍스트 의 현재 문 자 를 일치 시 키 고 일치 하 는 문 자 를 단어 후보 집합 에 추가 합 니 다.
여기 서 CJKSegmenter 를 상세 하 게 소개 하고, 기타 두 단어 기 는 CJKSegment 와 다른 것 만 설명 하면 된다.
상위 코드:
public void analyze(AnalyzeContext context) {
        if(CharacterUtil.CHAR_USELESS != context.getCurrentCharType()){          
            //    tmpHits  hit
            if(!this.tmpHits.isEmpty()){
                //      
                Hit[] tmpArray = this.tmpHits.toArray(new Hit[this.tmpHits.size()]);
                for(Hit hit : tmpArray){
                    hit = Dictionary.getSingleton().matchWithHit(context.getSegmentBuff(), context.getCursor() , hit);
                    if(hit.isMatch()){
                        char[] date = context.getSegmentBuff();
                        //      
                        Lexeme newLexeme = new Lexeme(context.getBufferOffset() , hit.getBegin() , context.getCursor() - hit.getBegin() + 1 , Lexeme.TYPE_CNWORD);
                        context.addLexeme(newLexeme);
                        if(!hit.isPrefix()){//     ,hit       ,  
                            this.tmpHits.remove(hit);
                        }                       
                    }else if(hit.isUnmatch()){
                        //hit   ,  
                        this.tmpHits.remove(hit);
                    }                    
                }
            }            
            
            //*********************************
            //                 
            Hit singleCharHit = Dictionary.getSingleton().matchInMainDict(context.getSegmentBuff(), context.getCursor(), 1);
            if(singleCharHit.isMatch()){//    
                //      
                Lexeme newLexeme = new Lexeme(context.getBufferOffset() , context.getCursor() , 1 , Lexeme.TYPE_CNWORD);
                context.addLexeme(newLexeme);
                //       
                if(singleCharHit.isPrefix()){
                    //       hit  
                    this.tmpHits.add(singleCharHit);
                }
            }else if(singleCharHit.isPrefix()){//      
                //       hit  
                this.tmpHits.add(singleCharHit);
            }
        }else{
            //  CHAR_USELESS  
            //    
            this.tmpHits.clear();
        }
        
        //           
        if(context.isBufferConsumed()){
            //    
            this.tmpHits.clear();
        }
        
        //         
        if(this.tmpHits.size() == 0){
            context.unlockBuffer(SEGMENTER_NAME);            
        }else{
            context.lockBuffer(SEGMENTER_NAME);
    }
}
<span style="font-family:  ;font-size:18px;"></span>

한 마디 한 마디 로 분석 하 다.
  • 문자 유형 을 판단 하고 문자 유형 은 텍스트 포인 터 를 이동 할 때 계산 한 것 으로 중국어, 한글, 일본어, 자모, 숫자, 기타 등
  • 을 포함한다.
  • 여기 CHARUSELESS 는 다른 유형의 문자 로 문자 형식 이 인식 되 지 않 으 면 아래 의 일치 절 차 를 건 너 뜁 니 다
  • .
    if(CharacterUtil.CHAR_USELESS != context.getCurrentCharType())
  • 여기 서 첫 번 째 if 조건 을 건 너 뛰 고 뒤의 코드 를 보 세 요.matchInMainDict 의 역할 은 일치 하 는 현재 문 자 를 main2012. dic 사전 에서 생 성 된 사전 수 에 비교 하 는 것 입 니 다
  • Hit singleCharHit = Dictionary.getSingleton().matchInMainDict(context.getSegmentBuff(), context.getCursor(), 1);
  • 비교 하 는 방식 은 전형 적 인 사전 트 리 이다. 사전 트 리 의 모든 노드 는 DictSegmenter 로 표시 하고 각 노드 의 다음 노드 는 Array 나 Map 으로 표시 하 며 dictSegmenter 류 는 다음 과 같다.
  • nodechar 는 현재 노드 에 저 장 된 2 바이트 문자
  • 를 표시 합 니 다.
  • node Status 는 이 노드 의 문자 가 사전 의 한 단어의 끝 문자 인지 아 닌 지 를 나타 낸다
  • 하급 노드 수량 에 따라 array 또는 map 를 선택 하여 하급 노드 분기
  • 를 저장 합 니 다.
  • 매 칭 시 한 글자 만 처리
  • 사전 트 리 원리 구 글 트 리
  • public class DictSegment implements Comparable<DictSegment>{
        
        //     ,    
        private static final Map<Character , Character> charMap = new HashMap<Character , Character>(16 , 0.95f);
        //      
        private static final int ARRAY_LENGTH_LIMIT = 3;
        //Map    
        private Map<Character , DictSegment> childrenMap;
        //        
        private DictSegment[] childrenArray;
        //          
        //private Character nodeChar;
        public Character nodeChar;
        //       Segment  
        //storeSize <=ARRAY_LENGTH_LIMIT ,      , storeSize >ARRAY_LENGTH_LIMIT ,   Map  
        private int storeSize = 0;
        //  DictSegment   ,   0 , 1                   
        private int nodeState = 0;
  • analysis 함수 로 돌아 가기
  • 이 코드 는 현재 문자 가 일치 하고 사전 의 한 글자 에 일치 하 는 단 어 를 나타 낸다. 쉽게 말 하면 사전 의 한 단어
  • 를 명중 시 켰 다.
  • addLexeme, 일치 하 는 단 어 를 단어 후보 집
  • 에 추가 합 니 다.
  • 일치 하 는 단어 가 다른 단어의 접두사 라면 뒤에 계속 일치 해 야 합 니 다. tmpHits 목록 에 추가 합 니 다
  • if(singleCharHit.isMatch()){//    
                    //      
                    Lexeme newLexeme = new Lexeme(context.getBufferOffset() , context.getCursor() , 1 , Lexeme.TYPE_CNWORD);
                    context.addLexeme(newLexeme);
    
                    //       
                    if(singleCharHit.isPrefix()){
                        //       hit  
                        this.tmpHits.add(singleCharHit);
                    }
  • 단어 가 일치 하지 않 고 접두사 만 일치 하 며 tmpHits 목록 에 추가 합 니 다
  • else if(singleCharHit.isPrefix()){//      
                    //       hit  
                   this.tmpHits.add(singleCharHit);
               }
  • 이제 아까 우리 가 뛰 어 넘 었 던 그 큰 if 문구 로 돌아 갈 수 있 습 니 다
  • 분명 합 니 다. tmpHits 가 비어 있 지 않 습 니 다. 위의 코드 가 특정한 단어의 접두사 와 일치 한 다 는 것 을 설명 합 니 다
  • 코드 는 다시 붙 이지 않 습 니 다. 이 기능 은 접두사 가 일치 하 는 문 자 를 꺼 내 현재 문자 와 조합 하여 사전 의 단어 나 단어 접두사 와 계속 일치 할 수 있 는 지 판단 하 는 것 입 니 다. 어미 에 맞 으 면 단어 후보 집 을 추가 하 는 것 입 니 다.접두사 로 남아 있 으 면 다음 라운드 가 계속 일치 합 니 다
  • 여기 서 일치 하 는 단 어 는 모두 두 글자 이상 의 단어 입 니 다. 한 글자 의 단 어 는 위의 코드 에서 일치 합 니 다
  • 계속 아래로 일치 하지 않 으 면 tmpHits 에서 이 문 자 를 제거 합 니 다
  • if(!this.tmpHits.isEmpty()
  • 이 과정 을 간단하게 요약 합 니 다. 매번 한 글자 가 일치 할 때마다 텍스트 포인 터 를 뒤로 이동 하고 analysis () 함수 일치 문 자 를 계속 호출 합 니 다. 사전 에 있 는 단어 와 일치 하면 단어 후보 집
  • 에 추가 합 니 다.
    핵심 사고방식 은 사실 간단 하 다, CNQuantifier Segmenter 와 Letter Segmenter 의 단어 코드 는 더 이상 상세 하 게 설명 하지 않 습 니 다. 코드 는 CJK 와 유사 합 니 다. 주요 차이 점 은 다음 과 같 습 니 다.
    1. CN_Quantifier Segmenter 의 사전 출처 두 곳: 1. quantifier. dic 파일, 양사 2. 수 사 를 포함 하여 Chn NumberChars 류 에 직접 썼 습 니 다. 내용 은 다음 과 같 습 니 다.
    2. Letter Segmenter 는 각각 세 개의 유사 한 프로세서 가 있 는데 그것 이 바로 자모, 숫자, 자모 와 숫자의 조합 이다.
    3. 처리 의 기본 적 인 사 고 는 똑 같은 유형의 문자 와 일치 하 는 것 이다. 서로 다른 유형의 문자 가 나타 날 때 까지 한 단 어 를 자 르 는 것 이다. 예 를 들 어 LetterSegmenter 가 문자열 에 대한 '중국어 abc 영어' 처리 방식 은 바로 연속 적 인 알파벳 문자열 abc 와 일치 하 는 것 이다. 한 단어 로 자 르 고 절 사 결 과 는 중국어 abc 영어 이다.
     
    절 사 는 이해 하기 어렵 지 않 죠? 뒤에 또 다른 핵심 내용 으로 들 어 갑 니 다. 잘못된 의미 로 처리 합 니 다.
     
    IK 분사 소스 분석 연재 (三) -- 잘못된 의미 처리

    좋은 웹페이지 즐겨찾기