hihocoder 1084 (哈希)
阅读原文时间:2023年07月10日阅读:1

题目链接

时间限制:4000ms

单点时限:4000ms

内存限制:256MB

描述

你知道KMP吗?它是用于判断一个字符串是否是另一个字符串的子串的算法。今天我们想去扩展它。

在信息理论中,在两个相同长度的字符串之间的海明码距离是:两个字符串相同位置对应的字符不同的位置数目。换种说法,它表示将一个字符串转化为另一个字符串所需要改变字符的最小数目。

下面这些字符串之间的海明码距离:

"karolin"和"kathrin"是3.

"karolin"和"kerstin"是3.

1011101和1001001是2.

2173896和2233796是3.

现在给定两个字符串stra,strb,和一个整数k。对于stra中的一个子串,如果它的长度和strb的相同且它们之间的海明码距离不超过k,我们认为它们是匹配的。

那么我们想知道在stra中有多少子串是和strb是匹配的。

输入

有多组测试(大约100),每个用例占3行。

第一行是stra。

第二行是strb。

第三行是k。

请处理到文件末尾。

【参数说明】

1<=stra,strb的长度<=100000

stra,strb只包含小写字母

0<=k<=5

输出

对于每个测试用例,以输出结果占一行。

样例输入

abcde
f
0
abcde
f
1
karolin
kathrin
3

样例输出

0
5
1

AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

#define mem(a, b) (memset(a, b, sizeof(a)))
#define pb push_back
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define rep(i, m) for (int i = 0; i < (int)(m); i++) #define rep2(i, n, m) for (int i = n; i < (int)(m); i++) typedef unsigned long long ULL; typedef pair pii;

const int oo = (int) 1e9;
const double PI = * acos();
const double eps = 1e-;

const int P = ;
const int MAX_N = ;
ULL ha[MAX_N], hb[MAX_N];
ULL p[MAX_N];

ULL get(ULL h[], int l, int r) {
return h[r] - h[l] * p[r - l];
}

char sa[MAX_N], sb[MAX_N];
int main(void) {
p[] = ;
for (int i = ; i < MAX_N; ++i)
p[i] = p[i - ] * P;

 while (~scanf("%s", sa + )) {  
     scanf("%s", sb + );  
     int k;  
     scanf("%d", &k);

     int lenA = strlen(sa + );  
     int lenB = strlen(sb + );  
     for (int i = ; i <= lenA; ++i) {  
         ha\[i\] = ha\[i - \] \* P + sa\[i\];  
     }  
     for (int i = ; i <= lenB; ++i) {  
         hb\[i\] = hb\[i - \] \* P + sb\[i\];  
     }

     int ans = ;  
     for (int i = lenB; i <= lenA; ++i) {  
         int cnt = ;

         int za = i, zb = lenB;  
         while (  ) {  
             int l = , r = zb + ;  
             while (r - l > ) {  
                 int mid = (l + r) >> ;  
                 if (get(ha, za - mid, za) == get(hb, zb-mid, zb)) {  
                     l = mid;  
                 } else {  
                     r = mid;  
                 }  
             }  
             //printf("l: %d\\n", l);  
             if (l == zb) break;  
             za -= l + ;  
             zb -= l + ;  
             ++cnt;  
             if (cnt > k) break;  
             if (zb <= ) break;  
         }

         if (cnt <= k) ++ans;  
     }  
     printf("%d\\n", ans);  
 }

 return ;  

}