영원한사랑


<?
# 특징: 본문 중에 나타난 모든 욕들을 한꺼번에 콤마로 구분하여 리턴

# 방법: 속도를 고려하여 전진방식의 매칭으로 처리
# 매칭할 단어들을 배열A에 저장해 놓는다.
# 함수로 위 단어의 첫글자를 따로 배열B로 만든다.
# 본문을 한글자씩 전진하면서 그 글자랑 매칭되는 문자가 있는지 B배열을 채크한다.
# B배열은 A배열에서 그 문자로 시작하는 첫 단어의 index를 가지고 있으며
# A배열의 그 위치부터 현재 문서 위치의 문자열이랑 비교를 하는데,
# 문자열 비교를 위하여 문서로부터 단어 최대길이만큼 짤라서 비교를 한다.
# 저작권: 니맘 대로 하세요.

# 필터링할 단어들. 정렬되어 있어야 한다.
# 심한 욕들이 있어서 첨부파일로 넣었습니다.
include "words_text.php";

# [수집된 단어의 첫 2바이트] => 그 글자가 처음 나오는 단어의 인덱스
#
function get_indexOfWords(&$words)
{
  $arr= array();
  $ch_old=0;
  foreach($words as $k=>$v){
    $ch= $v{0}.$v{1};
    if ($ch_old==$ch) continue;

    $ch_old=$ch;
    $arr[$ch]= $k;
  }
  return $arr;
}

# 상수
# 배열값 중에서 가장 긴 길이와 같거나 더 길면 됨. 정확하지 않아도 무방..
# 왜냐면, 본문 중에서 비교할 문자열을 적당히 짜를 용도이므로
define('MEX_WORD_LEN', 10);

function fuck_match (&$words, $str)
{
  $RET_WORDS= array();
  $char2idx= array();

  $char2idx= get_indexOfWords($words);
  $num_words= sizeof($words);
  $len_str= strlen($str);

  $han_flag=0;
  for ($i=0; $i<$len_str; $i++){
    if ($han_flag){      # 한글의 두번째 바이트 차례는 건너뜀
      $han_flag=0;
      continue;
    }
    $ch= $str{$i};
    if (127 < ord($ch)){
      $ch.= $str{$i+1};  # 한글이면 2바이트를 1글자로 처리
      $han_flag=1;
    }

    if (! isset($char2idx[$ch]))  # 첫글자가 일치하는 단어의 인덱스가 없으면 건너뜀
      continue;

    $str_part= substr($str, $i, MEX_WORD_LEN);  # 본문 중에 비교할 부분 문자열

      // echo "@$i@ 단어의 첫글자 일치의 경우  ($str_part == {$words[$char2idx[$ch]]})<br>";

    $match_word= '';
    for($j=$char2idx[$ch]; $j< $num_words; $j++){
      if (strpos($str_part, $words[$j])===0) # 단어가 완전히 포함되면
        $match_word= $words[$j];            # 임시저장
      if ($str_part<= $words[$j]){    # 단어가 비교 문자열보다 커지는 순간에 탈출
        if ($match_word!='')
          $RET_WORDS[]= $match_word;  # 그 순간의  임시 단어 수집
        break;
      }
    }
    if ($match_word && $j==$num_words){
    // echo "@$i@ 정렬에 문제가 있어서 저장 못하고 지나왔다면? ($match_word)<br>";
      $RET_WORDS[]= $match_word;
    }
  }
  if(0==sizeof($RET_WORDS))    return '';

  return implode(', ', array_unique($RET_WORDS));  # 중복 제거하고 리턴
}


#--------------- 요 밑으로는 테스트 --------------------------#

function __get_microtime(){
  list($usec, $sec)=  explode(" ",microtime());
  return (float)$usec + (float)$sec;
}


$time_start= __get_microtime();

$test_str= <<<TEST
여기는  별의별 헛소리를 다 넣어도 된다 무조껀 뻐큐
테스트용 문자열이므로 아무 의미가 없습니다 자세히 읽어 보지 말기를 바랍니다.
하하 호호 히히 쉽 스까이
내가 생각하는 아이템 사이트에서는
사실은 자유게시판이 아니라 회원제에서는 욕이 나오기는 힘들고 관리하기도 쉽다.
따라서 무단광고, 성인광고 처리에 집중하자.
일부러 표기법을 어기거나 특수분자랑 뒤섞는 등의 "정해지지 않는" 단어 처리에 대해서는
쉽게 생각하면 새로운 광고 단어 유형을 그때그때 수동으로 수집처리하면 된다.

자동으로 처리하려면?
광고 단어의 글자 사이에 특수문자들을 끼워 넣은 경우를 매칭하기 위하여
공백을 포한한 특수문자는 모두 제거하고 매칭할까.
3글자 이상의 길이면 가능하겠는데. 이런 좁밥

2글자 이하의 매칭은 특수문자 제거하고 매칭시 엉뚱한 문자열이 걸릴 수 있다. ㅅㅂㄹㅁ','凸','갈보
그러므로 2자 이하의 단어 매칭시 바로 광고라고 확정하지 말고 가중 점수로써 처리하자.
시발시발 시발 새새끼 개새끼
호홋
TEST;

$result= fuck_match ($words, $test_str);

echo "결과= ($result)<hr>실행에 걸린 시간=". (__get_microtime()- $time_start);
?>

펌:http://www.phpschool.com/gnuboard4/bbs/board.php?bo_table=tipntech&wr_id=57637&page=1