이 프로그램은 RMM 중국어 단어 분할 아이디어를 기반으로 한 간단한 중국어 단어 분할입니다. 프로그램에는 아직 허점이 많이 있습니다.
- /**
- * RMM 중국어 단어 분할 기준(역매칭 방식)
- * @author tangpan
- * @date 2013-10-12
- * @version 1.0.0
- **/
- class SplitWord {
- //public $Tag_dic = array() //스토리지 사전 단어 분할
- public $Rec_dic = array(); //저장소 단어 분할
- public $Split_char = ' '; //Separator
- public $Source_str = ''; public $Result_str = ''; //저장 단어 분할 결과 문자열
- public $limit_lenght = 2;
- public $Dic_maxLen = 28; //사전의 최대 단어 길이
- public $Dic_minLen = 2 ; //사전의 최소 단어 길이
-
- public function SplitWord() { //객체를 초기화하고 멤버 메서드를 자동으로 실행
- $this->__construct();
- }
- public function __construct() {
- $dic_path = dirname(__FILE__).'/words.csv'; //단어 분할 속도를 향상시키기 위해 사전을 미리 로드합니다
- $fp = fopen( $dic_path, 'r' ) ; / /어휘의 단어 읽기
- while( $line = fgets( $fp, 256 ) ) {
- $ws =explore(' ', $line) // 어휘의 단어 분할
- $ws[0] = Trim(iconv('utf-8','GBK',$ws[0])) //인코딩 변환
- //$this->Tag_dic[$ws[ 0 ]] = true; //워드를 인덱스로, 일련번호를 값으로 사용
- $this->Rec_dic[strlen($ws[0])][$ws[0]] = true; 단어는 각각 2차원 배열의 인덱스이며 n을 값으로 사용하여 어휘를 재구성합니다.
- }
- fclose($fp) // 어휘 닫기
- }
-
- /**
- * 소스 문자열 설정
- * @param 분할할 문자열
- */
- public function SetSourceStr( $str ) {
- $str = iconv( 'utf-8', 'GBK', $str ) // utf-8로 인코딩된 문자를 다음으로 변환합니다. GBK 인코딩
- $this->Source_str = $this->DealStr( $str ) //문자열 사전 처리
- }
-
- /**
- * 문자열 검사
- * @param $str 소스 문자열
- * @return bool
- */
- public function checkStr( $str ) {
- if ( Trim($str) == '' ) return; //문자열이 비어 있으면 직접 반환
- if ( ord( $str[0] ) > 0x80 ) return true; //한자이면 true를 반환
- else return false; //한자가 아니면 false를 반환
- }
-
-
- /* *
- * RMM 단어 분할 알고리즘
- * 처리할 @param $str 문자열
- */
- public function SplitRMM( $str = '' ) {
- if ( Trim( $str ) == '' ) return; //문자열이 비어 있으면 직접 반환
- else $this->SetSourceStr( $str ); //문자열이 비어 있지 않으면 소스 문자열을 설정합니다.
- if ( $this->Source_str == ' ' ) return; 비어 있으면 직접 반환
- $split_words =explore( ' ', $this->Source_str ); //문자열을 공백으로 분할합니다
- $lenght = count( $split_words ) //배열의 길이를 계산합니다.
- for ( $i = $lenght - 1; $i >= 0; $i-- ) {
- if ( Trim( $split_words[$i] ) == ' ' ) continue; 문자가 비어 있으면 다음 코드를 건너뛰고 다음 루프로 직접 입력
- if ( $this->checkStr( $split_words[$i] ) ) { //한자인지 문자열을 확인하세요
- if ( strlen( $split_words[$ i] ) >= $this->limit_lenght ) { //문자열 길이가 제한 크기보다 큰 경우
- //문자열 역일치
- $this- >Result_str = $this->pregRmmSplit ( $split_words[$i] ).$this->Split_char.$this->Result_str;
- }
- } else {
- $this-> ;Result_str = $split_words[$i].$this->Split_char.$this->Result_str;
- }
- }
- $this->clear( $split_words );
- return iconv('GBK', 'utf-8', $this->Result_str);
- }
-
- /**
- * 역방향 매칭 방식으로 중국어 문자열 분해
- * @param $str string
- * @return $retStr 단어 분할로 분할된 문자열
- */
- 공용 함수 pregRmmSplit( $ str ) {
- if ( $str == ' ' ) return;
- $splen = strlen( $str );
- $Split_Result = array();
- for ( $j = $splen - 1; $j >= 0; $ j--) { //역방향 일치 문자
- if ( $splen <= $this->Dic_minLen ) { //문자 길이가 최소 문자보다 큰 경우 사전의 길이
- if ( $j == 1 ) { //길이가 1인 경우
- $Split_Result[] = substr( $str, 0, 2 );
- }else {
- $w = Trim( substr( $str, 0, $this->Dic_minLen 1 ) ) //처음 4자를 자릅니다.
- if ( $this->IsWord( $w ) ) { //해당 문자가 사전에 존재하는지 확인
- $Split_Result[] = $w; //존재하는 경우 배열 저장소에 씁니다.
- } else {
- $Split_Result[] = substr( $ str, 2 , 2 ); //역저장
- $Split_Result[] = substr( $str, 0, 2 );
- }
- }
- $j = -1; loop;
- break;
- }
- if ( $j >= $this->Dic_maxLen ) $max_len = $this->Dic_maxLen; 사전의 최대 단어, 최대 제한 길이 할당
- else $max_len = $j;
- for ( $k = $max_len; $k >= 0; $k = $k - 2 ) { / /한 점프는 한자 한자
- $ w = Trim( substr( $str, $j - $k, $k 1 ) );
- if ( $this->IsWord( $w ) ) {
- $Split_Result[] = $w; / /단어 저장
- $j = $j - $k - 1 //일치하는 문자의 위치로 이동
- break; 단어 분할이 성공하면 현재 루프에서 빠져나와 다음 루프로 들어갑니다
- }
- }
- }
- $retStr = $this->resetWord( $Split_Result ) //문자열 재구성 처리된 문자열을 반환합니다
- $this->clear( $ Split_Result ); //메모리 해제
- return $retStr;
- }
-
- /**
- * 단어 세그먼트 재식별 및 결합
- * @param $Split_Result 대상 문자열 재구성
- * @return $ret_Str 문자열 재구성
- */
- 공개 함수 ResetWord( $Split_Result ) {
- if ( Trim( $Split_Result[0] ) == '' ) return;
- $Len = count( $Split_Result ) - 1;
- $ret_Str = ' ';
- $spc = $this->Split_char;
- for ( $i = $Len; $i >= 0; $i-- ) {
- if ( 트림( $Split_Result[$ i] ) != '' ) {
- $Split_Result[$ i] = iconv( 'GBK', 'utf-8', $Split_Result[$i] );
- $ret_Str .= $spc.$ Split_Result[$i].';
- }
- }
- //$ret_Str = preg_replace('/^'.$spc.'/',',',$ret_Str);
- $ret_Str = iconv('utf-8','GBK',$ ret_Str);
- return $ret_Str;
- }
-
- /**
- * 특정 단어가 사전에 존재하는지 확인
- * @param $okWord 확인된 단어
- * @return bool;
- */
- 공개 함수 IsWord ( $okWord ) {
- $len = strlen( $okWord ) ;
- if ( $len > $this->Dic_maxLen 1 ) return false;
- else { //2차원에 따르면 배열 인덱스 일치, 단어 존재 여부
- return isset($this-> Rec_dic[$len][$okWord]);
- }
-
- }
-
- /**
- * 예비 문자열 처리(특수문자를 공백으로 대체)
- * @param $str 처리할 소스 문자열
- * @return $okStr 전처리된 문자열을 반환
- */
- public function DealStr( $str ) {
- $spc = $this->Split_char; //구분자 복사
- $slen = strlen( $str ); of 문자
- if ( $slen == 0 ) return; //문자 길이가 0이면 바로 return
- $okstr = '' //초기화 변수
- $prechar = 0; 판단변수 (0-공백, 1-영어, 2-중국어, 3-기호)
- for ( $i = 0; $i < $slen; $i ) {
- $str_ord = ord( $str [$i] );
- if ( $str_ord < 0x81 ) { // 영문자인 경우
- if ( $str_ord < 33 ) { //영문 공백기호
- if ( $str [$i] != 'r' && $str[$i] != 'n' )
- $okstr .= $spc;
- $prechar = 0;
- 계속;
- } else if ( ereg('[@.%#:^&_-]',$str[$ i]) ) { //키워드 문자가 숫자, 영어, 특수문자인 경우
- if ( $prechar = = 0 ) { // 문자가 공백인 경우
- $okstr .= $str[$ i];
- $prechar = 3;
- } else {
- $okstr .= $spc .$str[$i]; //문자가 공백 문자가 아닌 경우 문자 앞에 공백 문자를 추가합니다.
- $prechar = 3;
- }
- } else if ( ereg(' [0-9a-zA-Z]', $str[$i]) ) { //영문 숫자 조합 분할
- if ( (ereg('[0-9]',$str[$i-1] ) && ereg('[a-zA-Z]',$str[$i]))
- || ( ereg('[a-zA-Z]',$str[$i-1]) && ereg('[0-9]',$str[$i])) ) {
- $okstr .= $ spc.$str[$i];
- } else {
- $okstr .= $str[$i];
- }
- }
- }else { //키워드의 두 번째 문자가 한자인 경우
- if ( $prechar != 0 && $prechar != 2 ) // 이전 문자가 한자가 아니고 공백이 아닌 경우 공백을 추가합니다.
- $okstr .= $spc;
- if ( isset( $str[$i 1] ) ) { //한자인 경우
- $c = $str[$i].$str [$i 1 ]; //두 문자열을 합쳐 한자를 만듭니다.
- $n = hexdec( bin2hex( $c ) ) //ASCII 코드를 16진수로 변환한 후 10진수로 변환합니다.
- if ( $n > 0xA13F && $n < 0xAA40 ) { //중국어 구두점인 경우
- if ( $prechar != 0 ) $okstr .= $spc //중국어 구두점을 공백으로 대체
- //else $okstr .= $spc; //이전 문자가 비어 있으면 직접 문자열로 지정
- $prechar = 3;
- } else { //중국어 구두점이 아닌 경우
- $ okstr .= $c;
- $prechar = 2;
- }
- $i; // $i는 한자씩 옮겨도 1씩 증가합니다
- }
- }
- }
- return $okstr;
- }
-
- /**
- * 메모리 해제
- * @param $data 임시 데이터
- */
- 공용 함수clear( $data ) {
- unset( $data ); //임시저장 데이터 삭제
- }
- }
- ?>
코드 복사
|