在开始之前,点个赞吧,球球了!
正文开始:
--------------------------------------(分割线)-------------------------------------------------
#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];:声明了两个全局字符数组a和b,每个数组最多可以存储10004个字符(最后一个字符留给空终止符\0)。char *pos;:声明一个指向字符的指针pos,用于存储匹配结果的位置。cin >> a >> b;:从标准输入读取两个字符串,分别存储在a和b中。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 .。.:*☆
820

被折叠的 条评论
为什么被折叠?



