KMP可以用于求一个模式串P在母串T中出现的次数和位置,时间复杂度是O(n + m) (n为P的长度,m为T的长度)。
进制哈希法也可以做到在O(n + m)的时间内求出P在T中出现的次数和位置,而且做法非常简单暴力!
还未了解进制哈希法的可以阅读下面两篇博客:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef unsigned long long ull;
const int maxn = 1e6 + 6;
const ull base1 = 13331;
const ull base2 = 233333;
char A[maxn], B[maxn];
ull h1[maxn], h2[maxn], p1[maxn], p2[maxn];
ull get_substring_hash(int l, int r, ull *h, ull *p){
return h[r] - h[l - 1] * p[r - l + 1];
}
int main(){
scanf("%s%s", A + 1, B + 1);
int lenA = strlen(A + 1), lenB = strlen(B + 1);
if(lenA < lenB){
printf("0\n");
}
else{
h1[0] = h2[0] = 0;
p1[0] = p2[0] = 1;
for(int i = 1; i <= lenA; ++i){
h1[i] = h1[i - 1] * base1 + (ull)A[i];
h2[i] = h2[i - 1] * base2 + (ull)A[i];
p1[i] = p1[i - 1] * base1;
p2[i] = p2[i - 1] * base2;
}
ull B_hash1 = 0, B_hash2 = 0;
for(int i = 1; i <= lenB; ++i){
B_hash1 = B_hash1 * base1 + (ull)B[i];
B_hash2 = B_hash2 * base2 + (ull)B[i];
}
int cnt = 0;
for(int i = 1; i <= lenA - lenB + 1; ++i){
ull hash1 = get_substring_hash(i, i + lenB - 1, h1, p1);
ull hash2 = get_substring_hash(i, i + lenB - 1, h2, p2);
if(hash1 == B_hash1 && hash2 == B_hash2)
++cnt;
}
printf("%d\n", cnt);
}
return 0;
}
以后如果没有或记不住KMP的模板,就可以用进制哈希来替代KMP啦!