【字符串】Rabin-Karp算法(RK算法)

在开始之前,点个赞吧,球球了!

正文开始:

--------------------------------------(分割线)-------------------------------------------------

#include <bits/stdc++.h>
#include <cmath>
#include <stdio.h>
using namespace std;
#define N 10005
char *RKSearch(char text[], char pattern[]);
char a[N], b[N];

int main() {
	char *pos;
	cin >> a >> b;
	pos = RKSearch(a, b);
	if (pos == nullptr) {
		cout << "No" << endl;
	} else {
		cout << pos - a << endl;
	}

	return 0;
}

char *RKSearch(char text[], char pattern[]) {
	const int BASE = 97;
	const int MOD = 10000007;
	int t = 1; //最高位的位权
	int tHash = 0, pHash = 0;
	int lent = strlen(text), lenp = strlen(pattern);
	if (lent == 0 || lenp == 0 || lent < lenp) {
		return nullptr;
	}
	for (int i = 0; i < lenp - 1; i++) {
		t = t * BASE % MOD;
	}
	for (int i = 0; i < lenp; i++) {
		pHash = (pHash * BASE + pattern[i]) % MOD;
		tHash = (tHash * BASE + text[i]) % MOD;
	}
	for (int i = 0; i <= lent - lenp; i++) {
		if (pHash == tHash) {
			int j;
			for (j = 0; j < lenp; j++) {
				if (pattern[j] != text[i + j]) {
					break;
				}
			}
			if (j == lenp) {
				return text + i;
			}
		}
		if (i < lent - lenp) {
			tHash = ((tHash - text[i] * t) * BASE + text[i + lenp]) % MOD;
			if (tHash < 0) {
				tHash += MOD;
			}
		}
	}
	return nullptr;
}

以上 是关于RK算法在C++里的实现

下面是解析:

  • #include <bits/stdc++.h>:这是一个包含几乎所有C++标准库头文件的预处理指令。
  • #include <cmath> 和 #include <stdio.h>:分别用于数学函数和C风格输入输出。
  • using namespace std;:使用标准命名空间,避免每次调用标准库函数时都要加上std::前缀。
  • #define N 10005:定义一个常量N,值为10005,用于数组的最大长度。
  • 全局变量声明

    char *RKSearch(char text[], char pattern[]);
    char a[N], b[N];

char *RKSearch(char text[], char pattern[]); char a[N], b[N];

  • char *RKSearch(char text[], char pattern[]);:声明了一个名为RKSearch的函数原型,该函数接受两个字符数组(文本和模式),返回指向匹配位置的指针。
  • char a[N], b[N];:声明了两个全局字符数组ab,每个数组最多可以存储10004个字符(最后一个字符留给空终止符\0)。

  • char *pos;:声明一个指向字符的指针pos,用于存储匹配结果的位置。
  • cin >> a >> b;:从标准输入读取两个字符串,分别存储在ab中。
  • pos = RKSearch(a, b);:调用RKSearch函数,在text中查找pattern,并将结果存储在pos中。
  • if (pos == nullptr):如果pos为空指针,表示没有找到匹配项,输出"No"。
  • else:否则,计算并输出匹配项在text中的起始索引(即pos - a)。
    char *RKSearch(char text[], char pattern[]) {
        const int BASE = 97;
        const int MOD = 10000007;
        int t = 1; // 最高位的位权
        int tHash = 0, pHash = 0;
        int lent = strlen(text), lenp = strlen(pattern);
        if (lent == 0 || lenp == 0 || lent < lenp) {
            return nullptr;
        }
        for (int i = 0; i < lenp - 1; i++) {
            t = t * BASE % MOD;
        }
        for (int i = 0; i < lenp; i++) {
            pHash = (pHash * BASE + pattern[i]) % MOD;
            tHash = (tHash * BASE + text[i]) % MOD;
        }
        for (int i = 0; i <= lent - lenp; i++) {
            if (pHash == tHash) {
                int j;
                for (j = 0; j < lenp; j++) {
                    if (pattern[j] != text[i + j]) {
                        break;
                    }
                }
                if (j == lenp) {
                    return text + i;
                }
            }
            if (i < lent - lenp) {
                tHash = ((tHash - text[i] * t) * BASE + text[i + lenp]) % MOD;
                if (tHash < 0) {
                    tHash += MOD;
                }
            }
        }
        return nullptr;
    }

  • const int BASE = 97; 和 const int MOD = 10000007;:定义基数和模数,用于哈希计算。
  • int t = 1;:初始化最高位的位权。
  • int tHash = 0, pHash = 0;:初始化文本和模式的哈希值。
  • int lent = strlen(text), lenp = strlen(pattern);:获取文本和模式的长度。
  • if (lent == 0 || lenp == 0 || lent < lenp):检查特殊情况,如果文本或模式为空,或者模式比文本长,则返回空指针。
  • for (int i = 0; i < lenp - 1; i++):计算最高位的位权t
  • for (int i = 0; i < lenp; i++):计算初始的模式和文本子串的哈希值。
  • for (int i = 0; i <= lent - lenp; i++):遍历文本的所有可能的起始位置,进行哈希比较。
    • if (pHash == tHash):如果哈希值相等,进一步逐字符比较以确认是否真正匹配。
    • for (j = 0; j < lenp; j++):逐字符比较模式和当前文本子串。
    • if (j == lenp):如果所有字符都匹配,返回匹配位置的指针。
    • if (i < lent - lenp):更新下一个文本子串的哈希值。
    • 总结

      这段代码通过Rabin-Karp算法高效地在一个文本字符串中查找另一个模式字符串的位置。它利用哈希技术减少不必要的字符比较,从而提高查找效率。

      ---------------------------------------(分割线)------------------------------------------------------------------

      点个赞和收藏吧,up做文章是真的不容易啊awa╰(*°▽°*)╯☆*: .。. o(≧▽≦)o .。.:*☆

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呱呱呱~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值