一篇文章讲清楚如何用哈希对字符串快速查询回文

本文介绍了一种通过字符串哈希映射技术,利用正序和逆序哈希值来快速判断子串是否为回文的算法。通过计算并存储每个子串的哈希值,实现了在O(1)时间内进行查询,提高了查询效率。
摘要由CSDN通过智能技术生成

字符串哈希映射(回文查询)

(多次判断[l,r]区段字符串是不是回文)

1、应用情景

给定一个文本字符串s,需要q次查询以[l,r](1<=l,r<=|s|)的子串是不是回文字符串。

2、原理

将字符串的每一个子串映射成一个数字(一般用unsigned long long自动取模),也就是说对于每一个不同子串,他们所对应的数字大概率是不同的。

3、实现

同过正序哈希映射和逆序哈希映射,可以实现对每一个子串的回文验证。

4、哈希函数

以正向为例     hash[i]=hash[i-1]*base+s[i]

5、代码实现

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=1e6+5;//N为字符串长度规模 
ull h1[N];//正向哈希 
ull h2[N];//反向哈希
ull base=233;//base表示进制   用大质数减少hash碰撞
ull p[N];//存储进制位数 如以24进制p[3]=24^3 
char s[N];//文本字符串
void solve()
{
	cin>>(s+1);//从1读取文本字符串   方便处理 
	//预处理
	int n=strlen(s+1);//字符串长度如abc n=3 
	p[0]=1;h1[0]=0;h2[0]=0;
	for(int i=1;i<=n;i++)
	{
		h1[i]=(h1[i-1]*base+s[i]);
		h2[i]=(h2[i-1]*base+s[n-i+1]);
		p[i]=(p[i-1]*base);
	}
	int q;//q次查询 
	cin>>q;
	while(q--)
	{
		int l,r;
		cin>>l>>r;
		if(h1[r]-h1[l-1]*p[r-l+1]==h2[n-l+1]-h2[n-r]*p[r-l+1])
		{
			cout<<"YES\n";
		}
		else
		{
			cout<<"NO\n";
		}
	}
} 
int main()
{
	solve();
}

6、判断依据

将子串的正向hash值反向hash值比较相等则说明回文

h1[r]-h1[l-1]*p[r-l+1]==h2[n-l+1]-h2[n-r]*p[r-l+1]

  • 16
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
判断一个字符串是否能组成回文,可以使用哈表来记录每个字符出现的次数。具体实现方法如下: 1. 定义一个哈表count,用于记录每个字符出现的次数。 2. 遍历字符串s的每个字符,将对应的count值加1。 3. 如果字符串s的长度为偶数,那么每个字符必须出现偶数次才能组成回文;如果字符串s的长度为奇数,那么只有一个字符可以出现奇数次,其它字符必须出现偶数次才能组成回文。 4. 遍历哈表count的每个元素,如果存在一个元素的值为奇数,且字符串s的长度为偶数,或者存在两个或以上的元素的值为奇数,那么字符串s不能组成回文;否则,字符串s可以组成回文。 具体代码实现如下: ```c #include <stdio.h> #include <string.h> int can_form_palindrome(char s[]) { int i, len = strlen(s); int count[26] = {0}; // 初始化计数器 for (i = 0; i < len; i++) { count[s[i] - 'a']++; // 统计每个字符出现的次数 } int odd_count = 0; // 记录出现奇数次的字符的个数 for (i = 0; i < 26; i++) { if (count[i] % 2 == 1) { odd_count++; if (len % 2 == 0 || odd_count > 1) return 0; // 不能组成回文 } } return 1; // 可以组成回文 } int main() { char s[1001]; scanf("%s", s); if (can_form_palindrome(s)) printf("YES\n"); else printf("NO\n"); return 0; } ``` 上述代码中,我们使用了一个长度为26的数组count来记录每个小写字母出现的次数。由于数组下标从0开始,因此需要将字符减去字符'a'的ASCII码值,才能得到正确的下标。如果出现奇数次的字符的个数超过了1个,或者字符串长度为偶数且存在出现奇数次的字符,那么字符串不能组成回文。如果没有上述情况,那么字符串可以组成回文

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值