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,如需转载请自行联系原作者



相关文章
|
JavaScript
Vue子组件监听父组件的事件
Vue子组件监听父组件的事件
617 0
Vue子组件监听父组件的事件
|
JavaScript Java API
如何接入阿里云短信服务 (完整指南)
如何接入阿里云短信服务 (完整指南)
56246 1
|
XML 存储 API
RAG效果优化:高质量文档解析详解
本文介绍了如何通过高质量的文档解析提升RAG系统整体的效果。
16539 15
|
Java 开发者
修改JAR文件工具
本文介绍了一款名为JarEditor的IDEA插件,该插件允许用户直接对JAR包内的文件进行增删改查操作,无需先行解压。通过简单的安装与使用步骤,大大简化了传统上需要解压缩、反编译、重新编译及打包的过程。此外,JarEditor还支持对混淆过的JAR文件进行字节码级别的修改,并提供了强大的搜索功能,支持大小写、全词匹配和正则表达式搜索。对于开发者而言,这款插件无疑极大提高了处理JAR文件的效率和便捷性。
658 14
|
9月前
|
机器学习/深度学习 API
有效的思考:模型思考效率评测
随着大语言模型的迅速发展,模型的推理能力得到了显著提升。特别是长推理模型(Long Reasoning Models),如OpenAI的o1、DeepSeek-R1、QwQ-32B和Kimi K1.5等,因其展现出类似人类的深度思考能力而备受关注。这些模型通过长时间推理(Inference-Time Scaling),能够在解码阶段不断思考并尝试新的思路来得到正确的答案。
365 0
|
边缘计算 人工智能 5G
5G 组网模式:NSA 与 SA 的比较与应用
5G 组网模式:NSA 与 SA 的比较与应用
5560 1
|
SQL Kubernetes 流计算
实时计算 Flink版产品使用问题之如何在Windows上运行
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
存储 安全 Devops
这个代码托管平台真的香!比 Github 速度更快!!!
这个代码托管平台真的香!比 Github 速度更快!!!
5753 0
这个代码托管平台真的香!比 Github 速度更快!!!
|
移动开发 Shell 测试技术
Realtek蓝牙Android10.0移植结束后的基本测试和常见问题分析
Realtek蓝牙Android10.0移植结束后的基本测试和常见问题分析