问题描述:

Rabin-Karp的预处理时间是O(m),匹配时间O( ( n - m + 1 ) m )既然与朴素算法的匹配时间一样,而且还多了一些预处理时间,那为什么我们还要学习这个算法呢?虽然Rain-Karp在最坏的情况下与朴素匹配一样,但是实际应用中往往比朴素算法快很多。而且该算法的期望匹配时间是O(n)【参照《算法导论》】,但是Rabin-Karp算法需要进行数值运算,速度必然不会比KMP算法快,那我们有了KMP算法以后为什么还要学习Rabin-Karp算法呢?个人认为学习的是一种思想,一种解题的思路,当我们见识的越多,眼界也就也开阔,面对实际问题的时候,就能找到更加合适的算法。比如二维模式匹配,Rabin-Karp就是一种好的选择。

而且Rabin-Karp算法非常有趣,将字符当作数字来处理,基本思路:如果Tm是一个长度为 |P| 的T的子串,且转换为数值后模上一个数(一般为素数)与模式字符串P转换成数值后模上同一个数的值相同,则Tm可能是一个合法的匹配。

该算法的难点就在于p和t的值可能很大,导致不能方便的对其进行处理。对这个问题有一个简单的补救办法,用一个合适的数q来计算p和t的模。每个字符其实十一个十进制的整数,所以p,t以及递归式都可以对模q进行,所以可以在O(m)的时间里计算出模q的p值,在O(n - m + 1)时间内计算出模q的所有t值。参见《算法导论》或http://net.pku.edu.cn/~course/cs101/2007/resource/Intro2Algorithm/book6/chap34.htm

递推式是如下这个式子:

ts+1 = (d ( ts -T[s + 1]h) + T[s + m + 1 ] ) mod q

例如,如果d = 10 (十进制)m= 5, ts = 31415,我们希望去掉最高位数字T[s + 1] = 3,再加入一个低位数字(假定 T[s+5+1] = 2)就得到:

ts+1 = 10(31415 - 1000*3) +2 = 14152

代码示例:

    1. *Copyright(c) Computer Science Department of XiaMen University
    2. *
    3. *Authored by laimingxing on: 2012年 03月 04日 星期日 18:18:28 CST
    4. *
    5. * @desc:
    6. *
    7. * @history
    8. */
    9. #include <stdio.h>
    10. #include <math.h>
    11. #include <assert.h>
    12. #include <string.h>
    13. #include <stdlib.h>
    14. #define d 256// number of characters in the alphabet
    15. #define PRIME 127 //A prime number
    16. void RABIN_KARP_MATCHER( char *T, char *P, int q)
    17. {
    18. assert( T && P && q > 0 );
    19. int M = strlen( P );
    20. int N = strlen( T );
    21. int i, j;
    22. int p = 0;//hash value for pattern
    23. int t = 0;//hash value for txt
    24. int h = 1;
    25. //the value of h would be "pow( d, M - 1 ) % q "
    26. for( i = 0; i < M - 1; i++)
    27. h = ( h * d ) % q;
    28. for( i = 0; i < M; i++ )
    29. {
    30. p = ( d * p + P[i] ) % q;
    31. t = ( d * t + T[i] ) % q;
    32. }
    33. //Slide the pattern over text one by one
    34. for( i = 0; i <= N - M; i++)
    35. {
    36. if( p == t)
    37. {
    38. for( j = 0; j < M; j++)
    39. if(T[i+j] != P[j])
    40. break;
    41. if( j == M )
    42. printf("Pattern occurs with shifts: %d\n", i);
    43. }
    44. //Caluate hash value for next window of test:Remove leading digit,
    45. //add trailling digit
    46. if( i < N - M )
    47. {
    48. t = ( d * ( t - T[i] * h ) + T[i + M] ) % q;
    49. if( t < 0 )
    50. t += q;//按照书上的伪代码会出现t为负的情况,则之后的计算就失败了。
    51. }
    52. }
    53. }
    54. int main(int argc, char* argv[])
    55. {
    56. char txt[] = "GEEKS FOR GEEKS";
    57. char pat[] = "GEEK";
    58. RABIN_KARP_MATCHER( txt, pat, 127 );
    59. return 0;
    60. }</SPAN>

Rabin-Karp【转载】的更多相关文章

  1. 算法——字符串匹配Rabin-Karp算法

    前言 Rabin-Karp字符串匹配算法和前面介绍的<朴素字符串匹配算法>类似,也是相应每一个字符进行比較.不同的是Rabin-Karp採用了把字符进行预处理,也就是对每一个字符进行相应进 ...

  2. Leetcode #28. Implement strStr()

    Brute Force算法,时间复杂度 O(mn) def strStr(haystack, needle): m = len(haystack) n = len(needle) if n == 0: ...

  3. Hash function

    Hash function From Wikipedia, the free encyclopedia   A hash function that maps names to integers fr ...

  4. LintCode ---- 刷题总结

    对于一个给定的 source 字符串和一个 target 字符串,你应该在 source 字符串中找出 target 字符串出现的第一个位置(从0开始).如果不存在,则返回 -1. 基本:两重for循 ...

  5. 九章lintcode作业题

    1 - 从strStr谈面试技巧与代码风格 必做题: 13.字符串查找 要求:如题 思路:(自写AC)双重循环,内循环读完则成功 还可以用Rabin,KMP算法等 public int strStr( ...

  6. 模式字符串匹配问题(KMP算法)

    这两天又看了一遍<算法导论>上面的字符串匹配那一节,下面是实现的几个程序,可能有错误,仅供参考和交流. 关于详细的讲解,网上有很多,大多数算法及数据结构书中都应该有涉及,由于时间限制,在这 ...

  7. Rolling Hash(Rabin-Karp算法)匹配字符串

    您可以在我的个人博客中访问此篇文章: http://acbingo.cn/2015/08/09/Rolling%20Hash(Rabin-Karp%E7%AE%97%E6%B3%95)%E5%8C%B ...

  8. 《算法》第五章部分程序 part 5

    ▶ 书中第五章部分程序,包括在加上自己补充的代码,Knuth-Morris-Pratt 无回溯匹配,Boyer - Moore 无回溯匹配,Rabin - Karp 指纹匹配 ● Knuth-Morr ...

  9. 字符串匹配&Rabin-Karp算法讲解

    问题描述: Rabin-Karp的预处理时间是O(m),匹配时间O( ( n - m + 1 ) m )既然与朴素算法的匹配时间一样,而且还多了一些预处理时间,那为什么我们还要学习这个算法呢?虽然Ra ...

  10. Leetcode Lect3 时间复杂度/空间复杂度

    时间复杂度 复杂度 可能对应的算法 备注 O(1) 位运算 常数级复杂度,一般面试中不会有 O(logn) 二分法,倍增法,快速幂算法,辗转相除法   O(n) 枚举法,双指针算法,单调栈算法,KMP ...

随机推荐

  1. 进入MVC处理通道

    这一篇主要讲如何通过Asp.net处理管道把请求交给MVC进行处理的(进入MVC处理通道). 首先来看一下经典的Asp.net处理管道的生命周期. 我们知道一个ASP.NET应用程序可以有多个Http ...

  2. 【Android Developers Training】 93. 创建一个空验证器

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  3. 1.如何安装matlab2016a

    下载:见网盘 安装教程: 解压安装文件,安装文件为 iso 格式,但是不能通过虚拟光驱安装,需要将 iso 文件用解压软件解压.注意,R2016b_win64_dvd1.iso 和 R2016b_wi ...

  4. Android Shape Divider

    安卓框架提供了一种LinearLayout 内部布局元素分割线的实现,建立一个指定长宽的矩形Shape: <?xml version="1.0" encoding=" ...

  5. Java分形

    目前笔者接触过的分形主要有一下几种: 1.类似Clifford的分形.这种分形的特点是:分形的初始坐标为(0,0),通过初始坐标经过大量的迭代,得到一系列的点,根据得到的点来绘制分形曲线.这类分形的参 ...

  6. usaco training 4.1.3 fence6 题解

    Fence Loops题解 The fences that surround Farmer Brown's collection of pastures have gotten out of cont ...

  7. 软考 程序员 下午考题 c语言 笔记

    1. 数组名 是表示数组空间首地址的指针常量,程序中不允许对常量赋值. 如 int  a[];   a就是数组名,表示数组控件首地址的指针常量 a = 0;是错误的,不允许对指针常量赋值 &a ...

  8. VPN断开后断网脚本

    有时在实际中需要,不能暴露自己的真实IP,不得不使用VPN,但是VPN的稳定性及易受网络环境影响,在VPN的暂时掉线之后,会暴露自己的真实IP,此时通过脚本操作路由表让VPN断线之后,电脑失去网络访问 ...

  9. Go学习笔记(一)Let's 干吧

    加 Golang学习 QQ群共同学习进步成家立业 ^-^ 群号:96933959 简介     Go是Google开发的一种 静态强类型.编译型,并发型,并具有垃圾回收功能的编程语言.为了方便搜索和识 ...

  10. JavaScript一个拖动元素的实例

    <script type="text/javascript" src="./whenReady.js"></script> <bo ...