字符串哈希

字符串哈希

哈希基本思想就是两个对象的映射,字符串哈希则是将一个字符串映射到一个数上,用这个数即可代表这个字符串,而这个数被称为哈希值

那么如何计算哈希值呢?

我们知道字符串的每个字符其实相等于一个数字,因此我们可以把每个字符串看成一个整数,之后将其转化为P进制下mod一个质数的数字,而这个数也就是这个字符串的哈希值。

例:"ABCD" -----> (A×P3+B×P2+C×P1+D×P0)modK

一般我们取P为131 或 13331, Q 为 264可以保证大部分情况下不出现哈希冲突

而mod Q 的操作我们可以通过将变量定义为unsigned long long来省略,因为在ull下当数值溢出范围后会自动对264取模

哈希前缀

我们定义h[i] 表示字符串第1个到第i个字符组成的子串的哈希值

那如何求l到r的子串哈希值呢?

结论:res = h[r] - h[l - 1] * p[r - l + 1]

**我们不能直接向前缀和那样h[r] - h[l - 1], 因为此时在h[r]中1 - l-1的哈希值与h[l - 1]并不相同,而差的值正好就是他们直接相差的位数,因此乘上prl+1即可,这里我们已经预处理p[i]来表示pi了 **

通过这样的方法在预处理后我们可以用O(1)的复杂度获得一段字符的哈希值,并利用哈希值高效完成一系列其他操作

例:841. 字符串哈希 - AcWing题库

代码示例:

//#pragma comment(linker,   "/STACK:10240000000000,10240000000000")
//#pragma GCC optimize(2)

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i=(a);i<=(b);++i)
#define per(i,b,a) for (int i=(b);i>=(a);--i)
#define lb lower_bound
#define ub upper_bound
#define pb push_back
#define itt iterator
#define endl '\n'
#define IOS ios::sync_with_stdio(0); cin.tie(0);
#define lowbit(x) x & (-x)
#define clr(x) memset(x, 0, sizeof(x));
#define fi first
#define se second
#define mp make_pair
#define MOD 1000000007
typedef vector<int> vii;
typedef vector<long long> vll;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef set<int> si;
typedef set<ll> sll;
ll ksm(ll a, ll b, ll p) {if (b == 0) return 1; ll ns = ksm(a, b >> 1, p); ns = ns * ns % p; if (b & 1) ns = ns * a % p; return ns;}		
const int MAXN = 0x7fffffff;

const int N = 1e5 + 5, P = 131;

ull p[N];
ull h[N];
int n, m;	
char str[N];

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

int main ()
{	
	//IOS;
	cin >> n >> m;
	cin >> str + 1;
	p[0] = 1;
	for(int i = 1; i <= n; i ++)
	{
		p[i] = p[i - 1] * P; //预处理p数组
		h[i] = h[i - 1] * P + str[i];//预处理哈希前缀数组
	}
	while(m --)
	{
		int l1, r1, l2, r2;
		cin >> l1 >> r1 >> l2 >> r2;
		if(get(l1, r1) == get(l2, r2)) puts("Yes");
		else puts("No");
	}
	return 0;
}	
/*

*/
posted @   Yra  阅读(536)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示