算法——字符串匹配之Rabin-Karp算法

前言

Rabin-Karp字符串匹配算法和前面介绍的《朴素字符串匹配算法》类似,也是对应每一个字符进行比较,不同的是Rabin-Karp采用了把字符进行预处理,也就是对每个字符进行对应进制数并取模运算,类似于通过某种函数计算其函数值,比较的是每个字符的函数值。预处理时间O(m),匹配时间是O((n-m+1)m)。

Rabin-Karp算法实现

伪代码:

Rabin_Karp_search(T, P, d,  q)
	n = T.length;
	m = P.length;
	h = d^(m-1)mod q;
	p = 0;
	t = 0;
	for i =1 to m
	   p = (d*p+P[i]) mod q;
	   t = (d*t+T[i])mod q;
	for i = 0 to n-m
		 if p==t
			 if P[1..m]==T[i+1..i+m]
			 print"Pattern occurs with shift"i
		 if i<n-m
			 t = d(t-T[i+1]h) + T[i+m+1]mod q

源码:

// Rabin Karp Algorithm 

#include<iostream>
#include<string>

using namespace std;

void Rabin_Karp_search(const string &T, const string &P, int d, int q)
{
    int m = P.length();
    int n = T.length();
    int i, j;
    int p = 0;  // hash value for pattern
    int t = 0; // hash value for txt
    int h = 1;

    // The value of h would be "pow(d, M-1)%q"
    for (i = 0; i < m-1; i++)
        h = (h*d)%q;

    // Calculate the hash value of pattern and first window of text
    for (i = 0; i < m; i++)
    {
        p = (d*p + P[i])%q;
        t = (d*t + T[i])%q;
    }

    // Slide the pattern over text one by one
    for (i = 0; i <= n - m; i++)
    {

        // Chaeck the hash values of current window of text and pattern
        // If the hash values match then only check for characters on by one
        if ( p == t )
        {
            /* Check for characters one by one */
            for (j = 0; j < m; j++)
               if (T[i+j] != P[j])
				   break;

            if (j == m)  // if p == t and pat[0...M-1] = txt[i, i+1, ...i+M-1]
               cout<<"Pattern found at index :"<< i<<endl;
        }

        // Calulate hash value for next window of text: Remove leading digit,
        // add trailing digit
        if ( i < n-m )
        {
            t = (d*(t - T[i]*h) + T[i+m])%q;

            // We might get negative value of t, converting it to positive
            if(t < 0)
              t = (t + q);
        }
    }
}

int main()
{
    string T = "Rabin–Karp string search algorithm: Rabin-Karp";
    string P = "Rabin";
    int q = 101;  // A prime number
	int d = 16;
    Rabin_Karp_search(T, P,d,q);
    system("pause");
    return 0;
}

参考资料:

《算法导论》

http://www.geeksforgeeks.org/searching-for-patterns-set-3-rabin-karp-algorithm/

时间: 2024-10-06 13:06:09

算法——字符串匹配之Rabin-Karp算法的相关文章

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

这两天又看了一遍<算法导论>上面的字符串匹配那一节,下面是实现的几个程序,可能有错误,仅供参考和交流. 关于详细的讲解,网上有很多,大多数算法及数据结构书中都应该有涉及,由于时间限制,在这就不重复了. 需要说明的是: stra:主串,及需要从中寻找模式串的字符串 strb:模式串 <算法导论>上面包括严蔚敏老师<数据结构>,字符串下表是按从1开始,并且<数据结构>一书中貌似吧字符串的第一个字符用来储存字符串长度.这里我改成了0. maxlen :字符串的最长

Rabin Karp 算法实战

关键字 Rabin karp 算法, C++, ubuntu 14.04, linux, big integer, gmp 为了计算冗余度, 我写出了如下算法 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59

算法——字符串匹配之KMP算法

前言 本节介绍Knuth-Morris-Pratt字符串匹配算法(简称KMP算法).该算法最主要是构造出模式串pat的前缀和后缀的最大相同字符串长度数组next,和前面介绍的<朴素字符串匹配算法>不同,朴素算法是当遇到不匹配字符时,向后移动一位继续匹配,而KMP算法是当遇到不匹配字符时,不是简单的向后移一位字符,而是根据前面已匹配的字符数和模式串前缀和后缀的最大相同字符串长度数组next的元素来确定向后移动的位数,所以KMP算法的时间复杂度比朴素算法的要少,并且是线性时间复杂度,即预处理时间复

字符串匹配的三种算法

下面将介绍三种有关字符串匹配的算法,一种是朴素的匹配算法,时间复杂度为O(mn),也就是暴力求解.这种方法比较简单,容易实现.一种是KMP算法,时间复杂度为O(m+n),该算法的主要任务是求模式串的next数组.另外还有一种对KMP算法的改进,主要是求nextval数组. 第一种朴素的匹配算法: int index(char str[], char subStr[]) { int i = 0, j = 0,index = 0; while (str[i] != '\0' && subStr

算法——字符串匹配之有限自动机算法

前言 上篇文章介绍<Rabin-Karp字符串匹配算法>,这里介绍有限自动机(Finite Automata)字符串匹配算法,有限自动机(Finite Automata)字符串匹配算法最主要的是计算出转移函数.即给定一个当前状态k和一个字符x,计算下一个状态:计算方法为:找出模式pat的最长前缀prefix,同时也是pat[0...k-1]x(注意:字符串下标是从0开始)的后缀,则prefix的长度即为下一个状态.匹配的过程是比较输入文本子串和模式串的状态值,若相等则存在,若不想等则不存在.有

算法——字符串匹配之BM算法

前言 Boyer-Moore算法是一种基于后缀匹配的模式串匹配算法(简称BM算法),后缀匹配就是模式串从右到左开始比较,但模式串的移动依然是从左到右的.在实践中,BM算法效率高于前面介绍的<KMP算法>,算法分为两个阶段:预处理阶段和搜索阶段:预处理阶段时间和空间复杂度都是是O(m+sigma),sigma是字符集大小,一般为256:在最坏的情况下算法时间复杂度是O(m*n):在最好的情况下达到O(n/m). BM算法实现 BM算法预处理过程 BM算法有两个规则分别为坏字符规则(Bad Cha

KMP算法字符串匹配

对于暴力搜索法,当搜索词对应的字符与字符串中的字符不匹配时.将搜索词整个后移一位,再从头逐个比较.这样做虽然可行,但是效率很差,因为你要把"搜索位置"移到已经比较过的位置,重比一遍. 应用KMP算法之后,则有: 移动位数=已匹配的字符数?对应的部分匹配值 "部分匹配值"就是"前缀"和"后缀"的最长的共有元素的长度. KMP算法实现代码如下: void prefixFun(char *pattern, int *preFun)

字符串匹配问题【KMP算法】

一.问题 给定两个字符串S和T,找出T在S中出现的位置. 二.朴素算法 当S[i] != T[j]时,把T往后移一位,回溯S的位置并重新开始比较.    (1) 成功匹配的部分(ABC)中,没有一样的字符 S: i A B C A B C E T: j A B C E       S: i A B C A B C E T: j   A B C E     S: i A B C A B C E T: j     A B C E   S: i A B C A B C E T: j       A B

Horspool算法-字符串匹配

不得不说ACM哪怕是没有结果,对于算法能力的训练是毋庸置疑的-- 因为老师划了重点,所以讲一下horspool的字符串匹配算法的原理吧. 先声明几个概念,被找的字符串称为匹配串,要找的字符串被称为模式串,当前和模式串相匹配的匹配串的子串被称为匹配子串(废话 在朴素算法中,我们要找一个匹配串是否存在模式串,例如HuangZhi is a genius的匹配串串和ChengJinSen的模式串,那么我们一开始用的方法是用: HuangZhi is(11 character) 去匹配: ChengJi