[字符串] KMP与字符哈希

KMP

首先,要知道在KMP算法里的 next 数组里,对操作的字符串到底存储了什么。

以当前字符为结尾的子串,真前缀与真后缀相同的最长长度。(注意:不是说回文;而且是“真”,也就是说,不会包含一整个原字符串)

字符串哈希

定义

用类似前缀和的形式以便求出任意一个子串的Hash值

自然溢出:ull类型的数据,是64位且不包含符号位的数据,溢出相当于是对 2^64 取模。

进制base

h[i] 计算的是字符串 s[1-i] 哈希值

计算

把前一个的值乘 base ,再加上本位的字符值。

要减去 h[l-1],且因为乘了base好几次,所以要减的是 h[l-1] 的 b[r-l+1] 的倍数。

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KMP算法是一种用于字符串匹配的算法,其中最关键的部分是构建next数组,用于指导模式串的匹配过程。在构建next数组的时候,可以使用字符串哈希的思想,将模式串的前缀和后缀进行哈希处理,然后进行比较,从而得出next数组。 具体实现如下: ```c #include <stdio.h> #include <string.h> #define ll long long const int N = 1e6 + 5, P = 131; char s[N], t[N]; int n, m; ll h[N], p[N], ht[N], pt[N], nxt[N]; void init() { p[0] = pt[0] = 1; for(int i = 1; i <= n; ++i) { h[i] = h[i - 1] * P + s[i]; p[i] = p[i - 1] * P; } for(int i = 1; i <= m; ++i) { ht[i] = ht[i - 1] * P + t[i]; pt[i] = pt[i - 1] * P; } } int check(int len) { for(int i = 1; i + len - 1 <= m; ++i) { ll h1 = ht[i + len - 1] - ht[i - 1] * pt[len]; ll h2 = h[len]; if(h1 == h2) return i; } return 0; } void getnxt() { int j = 0; nxt[1] = 0; for(int i = 2; i <= m; ++i) { while(j && t[j + 1] != t[i]) j = nxt[j]; if(t[j + 1] == t[i]) ++j; nxt[i] = j; } } int main() { scanf("%s%s", s + 1, t + 1); n = strlen(s + 1), m = strlen(t + 1); init(); getnxt(); int j = 0; for(int i = 1; i <= n; ++i) { while(j && t[j + 1] != s[i]) j = nxt[j]; if(t[j + 1] == s[i]) ++j; if(j == m) { printf("%d\n", i - m + 1); j = nxt[j]; } } return 0; } ``` 其中,h[i]表示s的前i个字符哈希值,ht[i]表示t的前i个字符哈希值。p[i]和pt[i]分别表示P的i次方。check函数用于检查长度为len的模式串是否在t中出现过,并返回第一次出现的位置。getnxt函数用于计算next数组。在主函数中,使用KMP算法进行匹配,当j等于m时,说明匹配成功,输出匹配的起始位置,并更新j为nxt[j],继续匹配。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值