Karp-Rabin Hash 用于 字符串查找

#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

inline
uint32_t kr_hash(char const *str, size_t len)
{
   uint32_t hash =0;
   unsigned char const*p =(unsigned char const*)(str);
   for (;len; --len) {
      hash = (hash<<1) + *p++;
   }
}

inline
uint32_t  kr_rehash(char a, char b, uint32_t h, int times) {
    typedef unsigned char uchar_t;
    return (((h) - (uchar_t)(a)*times) << 1) + (uchar_t)(b);
}


inline
int kr_times(size_t len)
{
    int times = 1;
     for (int i = 1; i < len; ++i)
         times = (times<<1);
     return times;
}

 

inline
char const* kr_strstr_start(char const *src, size_t src_len,
              char const * pattern, size_t pattern_len, uint32_t hash,
              uint32_t times)
{

   assert(pattern_len<=25); // pattern_len <= 25  char 。
   if(src_len < pattern_len) return NULL;

   uint32_t hx = hash;
   uint32_t hy = kr_hash(src, pattern_len);
  
   /* Searching */
   int j = 0;
   while (j <= src_len-pattern_len) {
      if (hx == hy && memcmp(pattern, src + j, pattern_len) == 0){
          hash = hy;
         return src+j;
      }
      hy = kr_rehash(src[j], src[j + pattern_len], hy, times);
      ++j;
   }
   return NULL;
}

inline
char const * kr_strstr_next(char const *src, size_t src_len,
              char const * pattern, size_t pattern_len,
              uint32_t hash, uint32_t times)
{
   if(src_len < pattern_len) return NULL;

   uint32_t hx = hash;
   /* Searching */
   int j = 0;
   uint32_t hy = kr_rehash(src[j], src[j + pattern_len], hash, times);
   ++j;

   while (j <= src_len-pattern_len) {
      if (hx == hy && memcmp(pattern, src + j, pattern_len) == 0){
         return src+j;
      }
      hy = kr_rehash(src[j], src[j + pattern_len], hy, times);
      ++j;
   }
   return NULL;
}

 

#include <vector>

inline
int strstr(char const *src, char const * pattern, std::vector<char const *> &result)
{
    char const * p = NULL;
    int n = 0;
    while(p = strstr(src, pattern)) {
        result.push_back(p);
        ++n;
    }
    return n;
}

inline
int kr_strstr(char const *src, size_t src_len, char const * pattern, size_t pattern_len, std::vector<char const *> &result)
{
    if(pattern_len > 25) {
        return strstr(src, pattern, result);
    }
    int n= 0;
    uint32_t hash = kr_hash(pattern, pattern_len);
    int times = 1<<(pattern_len-1);
    char const * p =kr_strstr_start(src, src_len, pattern, pattern_len,  hash, times);
    for(;p; ) {
        result.push_back(p);
        n++;
        int len = p - src;
        if(len > src_len) break;
        p = kr_strstr_next(p, src_len-len, pattern,  pattern_len, hash, times);
    }
    return n;
}

转载于:https://www.cnblogs.com/napoleon_liu/archive/2010/12/28/1919062.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
匹配是指在一个文本串中查找另一个模式串的过程。常用的串匹配算法有Naïve算法、Rabin-Karp算法和Knuth-Morris-Pratt算法。 1. Naïve算法 Naïve算法是最简单的串匹配算法,也称为暴力匹配算法。它的思路是从文本串的第一个字符开始,依次比较文本串中的每个字符是否与模式串中的字符相等。若不相等,则继续向后比较;若相等,则比较下一个字符,直到找到完全匹配的子串或文本串被匹配完为止。 Naïve算法的时间复杂度是O(mn),其中m和n分别是模式串和文本串的长度。当模式串和文本串长度相等时,最坏情况下时间复杂度达到O(n^2)。 2. Rabin-Karp算法 Rabin-Karp算法是一种基于哈希值的串匹配算法。它的思路是先将模式串和文本串都转换为哈希值,然后比较它们的哈希值是否相等。如果哈希值相等,则再逐个比较模式串和文本串中的字符是否相等。这种方法可以有效地减少比较次数,提高匹配效率。 Rabin-Karp算法的时间复杂度是O(m+n),其中m和n分别是模式串和文本串的长度。但是,由于哈希函数的不完全性和哈希冲突的存在,Rabin-Karp算法在某些情况下可能会出现误判。 3. Knuth-Morris-Pratt算法 Knuth-Morris-Pratt算法是一种基于前缀函数的串匹配算法。它的思路是先计算出模式串的前缀函数,然后利用前缀函数的信息来跳过已经匹配过的部分,减少比较次数。 具体来说,KMP算法在匹配过程中维护一个指针i和一个指针j,其中i指向文本串中当前匹配的位置,j指向模式串中当前匹配的位置。如果当前字符匹配成功,则i和j同时向后移动一位;如果匹配失败,则通过前缀函数计算出j需要跳转到的位置,使得前j-1个字符与文本串中的对应字符已经匹配成功,然后将j指向这个位置,i不变,继续比较下一个字符。 KMP算法的时间复杂度是O(m+n),其中m和n分别是模式串和文本串的长度。由于利用了前缀函数的信息,KMP算法可以在最坏情况下达到O(n)的时间复杂度,比Naïve算法和Rabin-Karp算法更加高效。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值