哈希映射和KMP

1.哈希映射

详解:

将一个字符串按特定的规则转化成一个数字;

每个字母对应一个id;

id(s[i])=s[i]-'x'+1

hash值:

hash[i]=hash[i-1]*p+id(s[i])

例如:

hash[1]=s1\\ hash[2]=s1*p+s2\\ hash[3]=s1*p^{2}+s2*p+s3 \\ hash[4]=s1*p^{^{3}}+s2*p^{2}+s3*p^{1}+s4

求某个区间的hash值即为;

例如求: 3 ,4哈希值:    s3*p+s4

即:hash[4]-hash[3-1]*p^{4-3+1}

归纳为

求l到r的哈希值

hash[r]-hash[l-1]*p^{r-l+1}

题目举例:

很久很久以前,森林里住着一群

兔子。有一天,兔子们想要研究自己的 DNA 序列。我们首先选取一个好长好长的 DNA 序列(小兔子是外星生物,DNA 序列可能包含 26 个小写英文字母),然后我们每次选择两个区间,询问如果用两个区间里的 DNA 序列分别生产出来两只兔子,这两个兔子是否一模一样。注意两个兔子一模一样只可能是他们的 DNA 序列一模一样。

AC代码:

#define _CRT_SECURE_NO_WARNINGS
#include<string>
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
const int mod = 1e5;
unsigned long long f[N], p[N];
char s[N];
int main()
{
	scanf("%s", s + 1);
	int n = strlen(s + 1), q;
	cin >> q;
	p[0] = 1;
	for (int i = 1; i <= n; ++i)
	{
		f[i] =( f[i - 1] * 131 + (s[i] - '0' + 1))%mod;//hash映射预处理
		p[i] = p[i - 1] * 131;
	}
	for (int i = 1; i <= q; ++i)
	{
		int l, r, x, y;
		scanf("%d%d%d%d", &l, &r, &x, &y);
		if (f[r] - f[l - 1] * p[r - l + 1] == f[y] - f[x - 1] * p[y - x + 1])
		{
			puts("Yes");
		}
		else
		{
			puts("No");
		}
	}
}

2.KMP题目:P4391 [BOI2009]Radio Transmission 无线传输 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题解:`

#define _CRT_SECURE_NO_WARNINGS
#include<string>
#include<iostream>
using namespace std;
const int N = 1e6 + 10;
const int mod = 1e5;
int n;
char s[N];
int _next[N];
void getnext()
{
	for (int i = 2, j = 0; i <= n; i++)
	{
		while (s[i] != s[j + 1] && j)
		{
			j = _next[j];//标记回溯的位置
		}
		if (s[i] == s[j + 1])
		{
			j++;
		}
		_next[i] = j;//不断更新 通过标记减少循环的时间
	}
}
int main()
{
	scanf("%d", &n);
	cin >> (s + 1);
	getnext();
	printf("%d\n", n - _next[n]);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值