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

本文详细介绍Rabin-Karp字符串匹配算法的原理及实现过程,包括预处理阶段、hash值计算方法以及滑动窗口匹配策略,并附带完整C++代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

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

预处理时间O(m)。匹配时间是O((n-m+1)m)

Rabin-Karp算法的思想:

  1. 如果待匹配字符串的长度为M,目标字符串的长度为N(N>M);
  2. 首先计算待匹配字符串的hash值,计算目标字符串前M个字符的hash值;
  3. 比較前面计算的两个hash值,比較次数N-M+1:
    • 若hash值不相等,则继续计算目标字符串的下一个长度为M的字符子串的hash值
    • 若hash值同样。则须要使用朴素算法再次推断是否为同样的字串;

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/

版权声明:本文博主原创文章。博客,未经同意不得转载。

转载于:https://www.cnblogs.com/zfyouxi/p/4877496.html

内容概要:本文档主要展示了C语言中关于字符串处理、指针操作以及动态内存分配的相关代码示例。首先介绍了如何实现键值对(“key=value”)字符串的解析,包括去除多余空格根据键获取对应值的功能,提供了相应的测试用例。接着演示了从给定字符串中分离出奇偶位置字符的方法,将结果分别存储到两个不同的缓冲区中。此外,还探讨了常量(const)修饰符在变量指针中的应用规则,解释了不同类型指针的区别及其使用场景。最后,详细讲解了如何动态分配二维字符数组,实现了对这类数组的排序与释放操作。 适合人群:具有C语言基础的程序员或计算机科学相关专业的学生,尤其是那些希望深入理解字符串处理、指针操作以及动态内存管理机制的学习者。 使用场景及目标:①掌握如何高效地解析键值对字符串去除其中的空白字符;②学会编写能够正确处理奇偶索引字符的函数;③理解const修饰符的作用范围及其对程序逻辑的影响;④熟悉动态分配二维字符数组的技术,能对其进行有效的排序清理。 阅读建议:由于本资源涉及较多底层概念技术细节,建议读者先复习C语言基础知识,特别是指针内存管理部分。在学习过程中,可以尝试动手编写类似的代码片段,以便更好地理解掌握文中所介绍的各种技巧。同时,注意观察代码注释,它们对于理解复杂逻辑非常有帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值