c#-SimHash匹配相似-算法

简介:

使用场景:Google 的 simhash 算法

//通过大量测试,simhash用于比较大文本,比如500字以上效果都还蛮好,距离小于3的基本都是相似,误判率也比较低。
 
//从我的经验,如果我们假定N是每个块的大小,M是重叠的字符的数目,N = 4和M = 3是最好的选择

  

public  class  SimHashAnalyser : IAnalyser
{
 
     private  const  int  HashSize = 32;
 
     public  float  GetLikenessValue( string  needle, string  haystack)
     {
         var  needleSimHash = this .DoCalculateSimHash(needle);
         var  hayStackSimHash = this .DoCalculateSimHash(haystack);
         return  (HashSize - GetHammingDistance(needleSimHash, hayStackSimHash)) / ( float )HashSize;
     }
 
     private  static  IEnumerable< int > DoHashTokens(IEnumerable< string > tokens)
     {
         var  hashedTokens = new  List< int >();
         foreach  ( string  token in  tokens)
         {
             hashedTokens.Add(token.GetHashCode());
         }
         return  hashedTokens;
     }
 
     private  static  int  GetHammingDistance( int  firstValue, int  secondValue)
     {
         var  hammingBits = firstValue ^ secondValue;
         var  hammingValue = 0;
         for  ( int  i = 0; i < 32; i++)
         {
             if  (IsBitSet(hammingBits, i))
             {
                 hammingValue += 1;
             }
         }
         return  hammingValue;
     }
 
     private  static  bool  IsBitSet( int  b, int  pos)
     {
         return  (b & (1 << pos)) != 0;
     }
 
     private  int  DoCalculateSimHash( string  input)
     {
         ITokeniser tokeniser = new  OverlappingStringTokeniser(4, 3);
         var  hashedtokens = DoHashTokens(tokeniser.Tokenise(input));
         var  vector = new  int [HashSize];
         for  ( var  i = 0; i < HashSize; i++)
         {
             vector[i] = 0;
         }
 
         foreach  ( var  value in  hashedtokens)
         {
             for  ( var  j = 0; j < HashSize; j++)
             {
                 if  (IsBitSet(value, j))
                 {
                     vector[j] += 1;
                 }
                 else
                 {
                     vector[j] -= 1;
                 }
             }
         }
 
         var  fingerprint = 0;
         for  ( var  i = 0; i < HashSize; i++)
         {
             if  (vector[i] > 0)
             {
                 fingerprint += 1 << i;
             }
         }
         return  fingerprint;
     }
 
 
}
 
 
 
public  interface  IAnalyser
{
     float  GetLikenessValue( string  needle, string  haystack);
}
 
public  interface  ITokeniser
{
     IEnumerable< string > Tokenise( string  input);
}
 
public  class  FixedSizeStringTokeniser : ITokeniser
{
     private  readonly  ushort  tokensize = 5;
     public  FixedSizeStringTokeniser( ushort  tokenSize)
     {
         if  (tokenSize < 2 || tokenSize > 127)
         {
             throw  new  ArgumentException( "Token 不能超出范围" );
         }
         this .tokensize = tokenSize;
     }
 
     public  IEnumerable< string > Tokenise( string  input)
     {
         var  chunks = new  List< string >();
         int  offset = 0;
         while  (offset < input.Length)
         {
             chunks.Add( new  string (input.Skip(offset).Take( this .tokensize).ToArray()));
             offset += this .tokensize;
         }
         return  chunks;
     }
 
}
 
 
public  class  OverlappingStringTokeniser : ITokeniser
{
           
     private  readonly  ushort  chunkSize = 4;
     private  readonly  ushort  overlapSize = 3;
 
     public  OverlappingStringTokeniser( ushort  chunkSize, ushort  overlapSize)
     {
         if  (chunkSize <= overlapSize)
         {
             throw  new  ArgumentException( "Chunck 必须大于 overlap" );
         }
         this .overlapSize = overlapSize;
         this .chunkSize = chunkSize;
     }
 
     public  IEnumerable< string > Tokenise( string  input)
     {
         var  result = new  List< string >();
         int  position = 0;
         while  (position < input.Length - this .chunkSize)
         {
             result.Add(input.Substring(position, this .chunkSize));
             position += this .chunkSize - this .overlapSize;
         }
         return  result;
     }
 
 
}

  

使用:

const  string  HayStack = "中国香港………………" ;
const  string  Needle = "中国香港 2013………………" ;
 
IAnalyser analyser = new  SimHashAnalyser();
var  likeness = analyser.GetLikenessValue(Needle, HayStack);
 
Console.Clear();
Console.WriteLine( "Likeness: {0}%" , likeness * 100);
Console.ReadKey();

  

 SimHash for c#


    本文转自曾祥展博客园博客,原文链接:http://www.cnblogs.com/zengxiangzhan/p/3311114.html,如需转载请自行联系原作者


相关文章
|
7月前
|
开发框架 算法 搜索推荐
C# .NET面试系列九:常见的算法
#### 1. 求质数 ```c# // 判断一个数是否为质数的方法 public static bool IsPrime(int number) { if (number < 2) { return false; } for (int i = 2; i <= Math.Sqrt(number); i++) { if (number % i == 0) { return false; } } return true; } class Progr
135 1
|
7月前
|
搜索推荐 算法 C#
【Unity 3D】C#中冒泡排序、选择排序、插入排序等算法的详解(附源码 超详细)
【Unity 3D】C#中冒泡排序、选择排序、插入排序等算法的详解(附源码 超详细)
128 1
|
1月前
|
算法 C#
C#常见的四种经典查找算法
C#常见的四种经典查找算法
|
1月前
|
算法 C# 索引
C#线性查找算法
C#线性查找算法!
|
2月前
|
存储 算法 C#
C#哈希查找算法
C#哈希查找算法
|
2月前
|
算法 C# 索引
C#二分查找算法
C#二分查找算法
|
2月前
|
机器学习/深度学习 算法 数据挖掘
使用C# 实现期望最大化算法
使用C# 实现期望最大化算法
53 0
|
3月前
|
存储 算法 C#
C#二叉搜索树算法
C#二叉搜索树算法
|
6月前
|
存储 编解码 算法
C#.NET逃逸时间算法生成分形图像的毕业设计完成!晒晒功能
该文介绍了一个使用C#.NET Visual Studio 2008开发的程序,包含错误修复的Julia、Mandelbrot和优化过的Newton三种算法,生成色彩丰富的分形图像。作者改进了原始算法的效率,将内层循环的画点操作移至外部,提升性能。程序提供五种图形模式,支持放大缩小及颜色更新,并允许用户自定义画布大小以调整精度。还具备保存为高质JPG的功能。附有四张示例图片展示生成的分形效果。
|
5月前
|
Dart 算法 JavaScript
C#数据结构与算法入门教程,值得收藏学习!
C#数据结构与算法入门教程,值得收藏学习!