>백엔드 개발 >PHP 튜토리얼 >RMM을 기반으로 한 간단한 중국어 단어 분할

RMM을 기반으로 한 간단한 중국어 단어 분할

WBOY
WBOY원래의
2016-07-25 08:49:341210검색
이 프로그램은 RMM 중국어 단어 분할 아이디어를 기반으로 한 간단한 중국어 단어 분할입니다. 프로그램에는 아직 허점이 많이 있습니다.
  1. /**
  2. * RMM 중국어 단어 분할 기준(역매칭 방식)
  3. * @author tangpan
  4. * @date 2013-10-12
  5. * @version 1.0.0
  6. **/
  7. class SplitWord {
  8. //public $Tag_dic = array() //스토리지 사전 단어 분할
  9. public $Rec_dic = array(); //저장소 단어 분할
  10. public $Split_char = ' '; //Separator
  11. public $Source_str = ''; public $Result_str = ''; //저장 단어 분할 결과 문자열
  12. public $limit_lenght = 2;
  13. public $Dic_maxLen = 28; //사전의 최대 단어 길이
  14. public $Dic_minLen = 2 ; //사전의 최소 단어 길이
  15. public function SplitWord() { //객체를 초기화하고 멤버 메서드를 자동으로 실행
  16. $this->__construct();
  17. }
  18. public function __construct() {
  19. $dic_path = dirname(__FILE__).'/words.csv'; //단어 분할 속도를 향상시키기 위해 사전을 미리 로드합니다
  20. $fp = fopen( $dic_path, 'r' ) ; / /어휘의 단어 읽기
  21. while( $line = fgets( $fp, 256 ) ) {
  22. $ws =explore(' ', $line) // 어휘의 단어 분할
  23. $ws[0] = Trim(iconv('utf-8','GBK',$ws[0])) //인코딩 변환
  24. //$this->Tag_dic[$ws[ 0 ]] = true; //워드를 인덱스로, 일련번호를 값으로 사용
  25. $this->Rec_dic[strlen($ws[0])][$ws[0]] = true; 단어는 각각 2차원 배열의 인덱스이며 n을 값으로 사용하여 어휘를 재구성합니다.
  26. }
  27. fclose($fp) // 어휘 닫기
  28. }
  29. /**
  30. * 소스 문자열 설정
  31. * @param 분할할 문자열
  32. */
  33. public function SetSourceStr( $str ) {
  34. $str = iconv( 'utf-8', 'GBK', $str ) // utf-8로 인코딩된 문자를 다음으로 변환합니다. GBK 인코딩
  35. $this->Source_str = $this->DealStr( $str ) //문자열 사전 처리
  36. }
  37. /**
  38. * 문자열 검사
  39. * @param $str 소스 문자열
  40. * @return bool
  41. */
  42. public function checkStr( $str ) {
  43. if ( Trim($str) == '' ) return; //문자열이 비어 있으면 직접 반환
  44. if ( ord( $str[0] ) > 0x80 ) return true; //한자이면 true를 반환
  45. else return false; //한자가 아니면 false를 반환
  46. }
  47. /* *
  48. * RMM 단어 분할 알고리즘
  49. * 처리할 @param $str 문자열
  50. */
  51. public function SplitRMM( $str = '' ) {
  52. if ( Trim( $str ) == '' ) return; //문자열이 비어 있으면 직접 반환
  53. else $this->SetSourceStr( $str ); //문자열이 비어 있지 않으면 소스 문자열을 설정합니다.
  54. if ( $this->Source_str == ' ' ) return; 비어 있으면 직접 반환
  55. $split_words =explore( ' ', $this->Source_str ); //문자열을 공백으로 분할합니다
  56. $lenght = count( $split_words ) //배열의 길이를 계산합니다.
  57. for ( $i = $lenght - 1; $i >= 0; $i-- ) {
  58. if ( Trim( $split_words[$i] ) == ' ' ) continue; 문자가 비어 있으면 다음 코드를 건너뛰고 다음 루프로 직접 입력
  59. if ( $this->checkStr( $split_words[$i] ) ) { //한자인지 문자열을 확인하세요
  60. if ( strlen( $split_words[$ i] ) >= $this->limit_lenght ) { //문자열 길이가 제한 크기보다 큰 경우
  61. //문자열 역일치
  62. $this- >Result_str = $this->pregRmmSplit ( $split_words[$i] ).$this->Split_char.$this->Result_str;
  63. }
  64. } else {
  65. $this-> ;Result_str = $split_words[$i].$this->Split_char.$this->Result_str;
  66. }
  67. }
  68. $this->clear( $split_words );
  69. return iconv('GBK', 'utf-8', $this->Result_str);
  70. }
  71. /**
  72. * 역방향 매칭 방식으로 중국어 문자열 분해
  73. * @param $str string
  74. * @return $retStr 단어 분할로 분할된 문자열
  75. */
  76. 공용 함수 pregRmmSplit( $ str ) {
  77. if ( $str == ' ' ) return;
  78. $splen = strlen( $str );
  79. $Split_Result = array();
  80. for ( $j = $splen - 1; $j >= 0; $ j--) { //역방향 일치 문자
  81. if ( $splen <= $this->Dic_minLen ) { //문자 길이가 최소 문자보다 큰 경우 사전의 길이
  82. if ( $j == 1 ) { //길이가 1인 경우
  83. $Split_Result[] = substr( $str, 0, 2 );
  84. }else {
  85. $w = Trim( substr( $str, 0, $this->Dic_minLen 1 ) ) //처음 4자를 자릅니다.
  86. if ( $this->IsWord( $w ) ) { //해당 문자가 사전에 존재하는지 확인
  87. $Split_Result[] = $w; //존재하는 경우 배열 저장소에 씁니다.
  88. } else {
  89. $Split_Result[] = substr( $ str, 2 , 2 ); //역저장
  90. $Split_Result[] = substr( $str, 0, 2 );
  91. }
  92. }
  93. $j = -1; loop;
  94. break;
  95. }
  96. if ( $j >= $this->Dic_maxLen ) $max_len = $this->Dic_maxLen; 사전의 최대 단어, 최대 제한 길이 할당
  97. else $max_len = $j;
  98. for ( $k = $max_len; $k >= 0; $k = $k - 2 ) { / /한 점프는 한자 한자
  99. $ w = Trim( substr( $str, $j - $k, $k 1 ) );
  100. if ( $this->IsWord( $w ) ) {
  101. $Split_Result[] = $w; / /단어 저장
  102. $j = $j - $k - 1 //일치하는 문자의 위치로 이동
  103. break; 단어 분할이 성공하면 현재 루프에서 빠져나와 다음 루프로 들어갑니다
  104. }
  105. }
  106. }
  107. $retStr = $this->resetWord( $Split_Result ) //문자열 재구성 처리된 문자열을 반환합니다
  108. $this->clear( $ Split_Result ); //메모리 해제
  109. return $retStr;
  110. }
  111. /**
  112. * 단어 세그먼트 재식별 및 결합
  113. * @param $Split_Result 대상 문자열 재구성
  114. * @return $ret_Str 문자열 재구성
  115. */
  116. 공개 함수 ResetWord( $Split_Result ) {
  117. if ( Trim( $Split_Result[0] ) == '' ) return;
  118. $Len = count( $Split_Result ) - 1;
  119. $ret_Str = ' ';
  120. $spc = $this->Split_char;
  121. for ( $i = $Len; $i >= 0; $i-- ) {
  122. if ( 트림( $Split_Result[$ i] ) != '' ) {
  123. $Split_Result[$ i] = iconv( 'GBK', 'utf-8', $Split_Result[$i] );
  124. $ret_Str .= $spc.$ Split_Result[$i].';
  125. }
  126. }
  127. //$ret_Str = preg_replace('/^'.$spc.'/',',',$ret_Str);
  128. $ret_Str = iconv('utf-8','GBK',$ ret_Str);
  129. return $ret_Str;
  130. }
  131. /**
  132. * 특정 단어가 사전에 존재하는지 확인
  133. * @param $okWord 확인된 단어
  134. * @return bool;
  135. */
  136. 공개 함수 IsWord ( $okWord ) {
  137. $len = strlen( $okWord ) ;
  138. if ( $len > $this->Dic_maxLen 1 ) return false;
  139. else { //2차원에 따르면 배열 인덱스 일치, 단어 존재 여부
  140. return isset($this-> Rec_dic[$len][$okWord]);
  141. }
  142. }
  143. /**
  144. * 예비 문자열 처리(특수문자를 공백으로 대체)
  145. * @param $str 처리할 소스 문자열
  146. * @return $okStr 전처리된 문자열을 반환
  147. */
  148. public function DealStr( $str ) {
  149. $spc = $this->Split_char; //구분자 복사
  150. $slen = strlen( $str ); of 문자
  151. if ( $slen == 0 ) return; //문자 길이가 0이면 바로 return
  152. $okstr = '' //초기화 변수
  153. $prechar = 0; 판단변수 (0-공백, 1-영어, 2-중국어, 3-기호)
  154. for ( $i = 0; $i < $slen; $i ) {
  155. $str_ord = ord( $str [$i] );
  156. if ( $str_ord < 0x81 ) { // 영문자인 경우
  157. if ( $str_ord < 33 ) { //영문 공백기호
  158. if ( $str [$i] != 'r' && $str[$i] != 'n' )
  159. $okstr .= $spc;
  160. $prechar = 0;
  161. 계속;
  162. } else if ( ereg('[@.%#:^&_-]',$str[$ i]) ) { //키워드 문자가 숫자, 영어, 특수문자인 경우
  163. if ( $prechar = = 0 ) { // 문자가 공백인 경우
  164. $okstr .= $str[$ i];
  165. $prechar = 3;
  166. } else {
  167. $okstr .= $spc .$str[$i]; //문자가 공백 문자가 아닌 경우 문자 앞에 공백 문자를 추가합니다.
  168. $prechar = 3;
  169. }
  170. } else if ( ereg(' [0-9a-zA-Z]', $str[$i]) ) { //영문 숫자 조합 분할
  171. if ( (ereg('[0-9]',$str[$i-1] ) && ereg('[a-zA-Z]',$str[$i]))
  172. || ( ereg('[a-zA-Z]',$str[$i-1]) && ereg('[0-9]',$str[$i])) ) {
  173. $okstr .= $ spc.$str[$i];
  174. } else {
  175. $okstr .= $str[$i];
  176. }
  177. }
  178. }else { //키워드의 두 번째 문자가 한자인 경우
  179. if ( $prechar != 0 && $prechar != 2 ) // 이전 문자가 한자가 아니고 공백이 아닌 경우 공백을 추가합니다.
  180. $okstr .= $spc;
  181. if ( isset( $str[$i 1] ) ) { //한자인 경우
  182. $c = $str[$i].$str [$i 1 ]; //두 문자열을 합쳐 한자를 만듭니다.
  183. $n = hexdec( bin2hex( $c ) ) //ASCII 코드를 16진수로 변환한 후 10진수로 변환합니다.
  184. if ( $n > 0xA13F && $n < 0xAA40 ) { //중국어 구두점인 경우
  185. if ( $prechar != 0 ) $okstr .= $spc //중국어 구두점을 공백으로 대체
  186. //else $okstr .= $spc; //이전 문자가 비어 있으면 직접 문자열로 지정
  187. $prechar = 3;
  188. } else { //중국어 구두점이 아닌 경우
  189. $ okstr .= $c;
  190. $prechar = 2;
  191. }
  192. $i; // $i는 한자씩 옮겨도 1씩 증가합니다
  193. }
  194. }
  195. }
  196. return $okstr;
  197. }
  198. /**
  199. * 메모리 해제
  200. * @param $data 임시 데이터
  201. */
  202. 공용 함수clear( $data ) {
  203. unset( $data ); //임시저장 데이터 삭제
  204. }
  205. }
  206. ?>
코드 복사
RMM을 기반으로 한 간단한 중국어 단어 분할


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.