问题描述:

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. [leetcode-557-Reverse Words in a String III]

    Given a string, you need to reverse the order of characters in each word within a sentence whilestil ...

  2. 【Android Developers Training】 34. 添加一个简单的分享行为(Action)

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

  3. 【技术解密】SequoiaDB分布式存储原理

    分布式架构势在必行 在传统的数据库技术中,为了保证数据的安全与高性能,通常会选择高端的外置存储作为数据库的主要存储源,而本地磁盘则被视为不可靠的性能低下的一种设备.这种观念的产生,主要是由于过去本地磁 ...

  4. Hibernate基础知识总结

    Hibernate是JDBC的轻量级的对象封装(encapsulation),它是一个独立的对象持久persistence层框架. hibernate要做的事,就是让对象投影到关系数据库中,然后实施化 ...

  5. JavaScript学习笔记(一)——初识js

    这个周,开始了JavaScript的学习路程.虽然从高中开始就接触了网页设计的知识,大学里的学习也算回顾了Html和Css的知识,实习期间在牛盾科技也是做的网站建设,不过通过前段时间找工作才发现自己了 ...

  6. JAVAEE——SSH三大框架整合(spring+struts2+hibernate)

    一.整合原理 二.导包(41个) 1.hibernate (1)hibernate/lib/required (2)hibernate/lib/jpa | java persist api java的 ...

  7. Oracle系统表实用操作笔记

    1.取得指定用户的所有表名: SQL1: SELECT OWNER AS "对象所有者", OBJECT_NAME AS "表名", OBJECT_ID AS ...

  8. C语言学习随笔

    前段时间我们学习了HTML,感觉自己不在状态,后来就开始怀疑自己的智商呢!现在C语言也到了尾声,在这20天的学习过程中,我没 有以前那么的傲娇了. 我开始慢慢去反省自己,自己究竟该如何去学习,都说勤能 ...

  9. tomcat支持php

    最近做项目遇到了问题,服务器是用的tomcat,而有用到php,就想在tomcat下面可以运行php,步骤如下: 1.下载php压缩包解压或者用wamp/xampp 我下载的是wamp,用的里面的ph ...

  10. MAC本上appium连接真机

    简单介绍一下appium连接ios真机测试环境的软件安装及配置过程: 目前我用的是desktop版本的appium, 所以MAC版本必须要升级到10.12以上,Xcode版本必须要在8.0以上,否则亲 ...