百度 搜索引擎 关键字 算法

因为过滤关键字机制到处可见,于是聪明的网友就会想到各种各样的方法突破,例如:        1 、中文会用繁体字的方法避开关键字扫描     2 、在关键字中间插入无意思的特殊字符,例如 * & # @ 等,而且个数可变     3 、使用谐音或拆字法变换关键字        在实现自己的算法时也有些问题:        4 、随着时间推移,关键字列表会越来越大,有些论坛常用的正则表达式N次扫描的方法显得效率很低。     5 、关键字有不同的严重级别,有些需要禁止,有些只需要替换,还有一些可能记录一下即可。           针对这些问题,可采用的应对方法:        1 、加载关键字列表时,将所有的关键字转换成繁体字一份,以扫描繁体版的关键字;     这个转换工作只需一句就可以实现了:     s=Microsoft.VisualBasic.Strings.StrConv(word, Microsoft.VisualBasic.VbStrConv.TraditionalChinese,  0 );        2 、在扫描原文本时,如果遇到关键字的首个文字,忽略其后的特殊字符,直到下一个有意义的文字为止,当然这里需要在定义关键字列表时指定哪些才需要这样扫描,并不是所有关键字都采用这种方式;     例如有关键字 “你好”经常会被人输入成“你x好”或者“你xxxxx好”,那么在关键字列表里就需要定义成“你*好”,在匹配关键字时,如果遇到星号就忽略原文本下一个为特殊的字符。        3 、遇到谐音和拆字时,没什么好办法了,只好将这些谐音词和拆分词也加入到关键字列表。        4 、不用正则表达式或者 String.IndexOf方法,可以将所有关键字的首字相同的组成一个一个小组,然后在将首字放到一个散列表(HashTable/Dictionary<T>),在扫描原文本时先在散列表里扫描,如果碰到了首字再扫描同组的关键字,这样简单处理一下效率可以提高很多。              还有一个比用散列表更好的方法,将散列表改成一个大小为 char .MaxValue的数组,然后将首个文字转成 int ,即 char -> int ,然后将关键词集合放到相应下标里。这样在扫描原文本时,将被扫描的字符转成 int ,然后试探数组相应下标的元素是否不为NULL。这样比用散列表会更快一些。        5 、在定义关键字时,同时给一个“级别”属性,例如使用 E,R,B分别表示只记录、替换、禁止等情况。     于是关键字的列表如下所示:     你滚 E     他niang的 R     成*人*网*站 B        这里贴一下关键的部分代码:              Code     private  WordGroup[] _wordTable;        public  FilterResult Filter(ref string source, char  replaceChar)     {     //NOTE::     // 如果方法返回 FilterResult.Replace或者FilterResult.Banned,则原字符串的某些字会被替代为星号,替代后的字符串可以由source取得        if  (String.IsNullOrEmpty(source))  return  FilterResult.Pass;        FilterResult result = FilterResult.Pass;     char [] tempString =  null ;        int  start =  0 ;     for  (; start < source.Length; start++)     {     WordGroup fw = _wordTable[fastToLower(source[start])];     if  (fw !=  null )     {     for  ( int  idx =  0 ; idx < fw.Count; idx++)     {     WordEntity we = fw.GetItem(idx);     int  matchLength= 0 ;     if  (we.Word.Length== 0  || checkString(source, we.Word, start +  1 , out matchLength))     {     FilterResult fr = we.HandleType;     if  (fr > result) result = fr;  //记录最高级别的处理方法     if  (fr == FilterResult.Replace || fr == FilterResult.Banned)     {     //替换关键字     if (tempString== null ) tempString =source.ToCharArray();;     for  ( int  pos =  0 ; pos < matchLength +  1 ; pos++)     {     tempString[pos + start] = replaceChar;     }     }     }     }     }     }        if  (result > FilterResult.RecordOnly)     {     source =  new  string(tempString);     }        return  result;     }        private  bool checkString(string source, string keyword,  int  sourceStart, out  int  matchLength)     {     bool found =  false ;     int  sourceOffset =  0 ;     int  keyIndex =  0 ;     for  (; keyIndex < keyword.Length; keyIndex++)     {     if  (sourceOffset + sourceStart >= source.Length)  break//原始字符串已经全部搜索完毕        if  (keyword[keyIndex] ==  '*' )     {     //跳过可忽略的字符     while  (sourceOffset + sourceStart < source.Length)     {     if  (isIgnorableCharacter_CN(source[sourceOffset + sourceStart]))     sourceOffset++;     else      break ;     }     }     else      {     //比较字母     if  (fastToLower(source[sourceOffset + sourceStart]) == ( int )keyword[keyIndex])     {     if  (keyIndex == keyword.Length -  1 )     {     found =  true ;     break ;     }     }     else      {     break ;     }        sourceOffset++; //移动原始字符串     }     }        //如果匹配中关键字,则返回原字符串中被匹配中的文字的长度,否则返回0     matchLength = sourceOffset +  1 ;     return  found;     }        private   int  fastToLower( char  character)     {     //将大写英文字母以及全/半角的英文字母转化为小写字母     int  charVal = ( int )character;     if  (charVal <=  90 )     {     if  (charVal >=  65//字母A-Z     return  charVal -  65  +  97 ;     }     else   if  (charVal >=  65313 )     {     if  (charVal <=  65338 )     return  charVal -  65313  +  97//全角大写A-Z     else   if  (charVal >=  65345  && charVal <=  65370 )     return  charVal -  65345  +  97//全角小写a-z     }     return  charVal;     }        private  bool isIgnorableCharacter_CN( char  character)     {     //NOTE::     // 中文表意字符的范围 4E00-9FA5     int  charVal = ( int )character;     return  !(charVal >=  0x4e00  && charVal <=  0x9fa5 );     }        // 单个过滤词条目     class  WordEntity     {     public  string Word { get; set; }     public  FilterResult HandleType { get; set; }     }        // 过滤词的组     class  WordGroup     {     //NOTE::用于装载一组具有同一个字开头的过滤词        private  List<WordEntity> _words;        public  WordGroup()     {     _words =  new  List<WordEntity>();     }        public   void  AppendWord(string word, FilterResult handleType)     {     AppendWord( new  WordEntity() { Word = word, HandleType = handleType });     }        public   void  AppendWord(WordEntity word)     {     _words.Add(word);     }        public   int  Count     {     get {  return  _words.Count; }     }        public  WordEntity GetItem( int  index)     {     return  _words[index];     }     } 

转载于:https://www.cnblogs.com/solomon_Blog/archive/2011/06/25/2089448.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值