zoukankan      html  css  js  c++  java
  • Rabin-Karp【转载】

    问题描述:

          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

    代码示例:

    [cpp] <SPAN style="FONT-SIZE: 18px">/* 
      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.   
      17.   
      18. void RABIN_KARP_MATCHER( char *T, char *P, int q)  
      19. {  
      20.     assert( T && P && q > 0 );  
      21.     int M = strlen( P );  
      22.     int N = strlen( T );  
      23.     int i, j;  
      24.     int p = 0;//hash value for pattern   
      25.     int t = 0;//hash value for txt   
      26.     int h = 1;  
      27.       
      28.     //the value of h would be "pow( d, M - 1 ) % q "       
      29.     for( i = 0; i < M - 1; i++)  
      30.         h = ( h * d ) % q;  
      31.   
      32.     for( i = 0; i < M; i++ )  
      33.     {  
      34.         p = ( d * p + P[i] ) % q;  
      35.         t = ( d * t + T[i] ) % q;  
      36.     }  
      37.       
      38.     //Slide the pattern over text one by one   
      39.     for( i = 0; i <= N - M; i++)  
      40.     {  
      41.         if( p == t)  
      42.         {  
      43.             for( j = 0; j < M; j++)  
      44.                 if(T[i+j] != P[j])  
      45.                     break;  
      46.             if( j == M )  
      47.                 printf("Pattern occurs with shifts: %d ", i);  
      48.         }  
      49.         //Caluate hash value for next window of test:Remove leading digit,   
      50.         //add trailling digit   
      51.         if( i < N - M )  
      52.         {  
      53.             t = ( d * ( t - T[i] * h ) + T[i + M] ) % q;  
      54.             if( t < 0 )  
      55.                 t += q;//按照书上的伪代码会出现t为负的情况,则之后的计算就失败了。   
      56.         }  
      57.     }  
      58. }     
      59.   
      60. int main(int argc, char* argv[])  
      61. {  
      62.     char txt[] = "GEEKS FOR GEEKS";  
      63.     char pat[] = "GEEK";  
      64.     RABIN_KARP_MATCHER( txt, pat, 127 );  
      65.       
      66.     return 0;  
      67. }</SPAN>  
  • 相关阅读:
    利用Session和HashTable制作购物车实例
    在windows 7上安装Maven2.2.1
    tail & cut 命令
    软件开发常用名词中英文对照
    字符,字节和编码
    grep 简介
    HSQLDB: java程序使用hsqldb 入门教程 java启动hsqldb
    eclipse 安装 maven 插件
    JNI 返回结构体参数
    HSQLDB 安装与使用
  • 原文地址:https://www.cnblogs.com/sandy2013/p/3261961.html
Copyright © 2011-2022 走看看