倒也不难,看一下源码就懂了,核心是把每一个字符串映射一个哈希值,通过哈希值就可以进行O(1)时间复杂度的每一次匹配
不同字符串哈希值可能相同,所以取模一个数,正常取值一般比较大
#include <bits/stdc++.h>
using namespace std;
int main()
{
const int q=114514;//手动狗头
// a~z ASCII
int ans = 0;
int t = 0, h = 0;
string T;
string P;
cin >> T ;//n
cin >> P; //m O( n-m+1 )m
unsigned long long int n,m;
n=T.length();
m=P.length();
cout <<"n = " << n << "m = " << m <<endl;
//预处理
for(int i=0;i<=m-1;i++){
h = (h+T[i])%q;
t = (t+P[i])%q;
t%=q;
}
//匹配
//说明 :这种算法在找长度为二的字串要加一个判断
//其实模式串长度越小,此算法的准确性越差,想要做到准确参考以下内容
//假设qwertytyty 寻找模式串 ty
//ty 和 yt 映射出来的哈希值是一样的
//在算法导论中,h == t 语句块里加上了一个判断两个字符串是否相等的语句块,但这里说的是长度为2的字串的情况
//《算法导论》 第3版 P582
for(int i=0;i<=n-m;i++){
if(h == t){
ans++;
}
h = (h-(int)T[i]+(int)T[i+m])%q;
}
cout <<"ans = " <<ans;
//整体的时间复杂度
//对于预处理O(m)
//对于匹配 O(n-m+1)
//总体的时间复杂度相加就好了
return 0;
}