ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

字符串哈希

2021-06-14 14:35:08  阅读:209  来源: 互联网

标签:shash 哈希 int ull 字符串 进制


字符串哈希

作用:把一个字符串变成一个很大的数字,可以用于判断字符串出现次数或两个串是否相等
  • 对数组、变量的定义:

string s:字符串 题目中要求s的hash

int base:一个较大质数 一般为233或23333 表示进制 字符串的哈希值实际上是一个base进制数

ull h[]:哈希值(前缀和) 使用ull是为了自然溢出 h[i]代表从字符串的第1位到第i为的哈希值

ull p[]:进制数组 p[i]=x表示字符串的第i位转换成数字时要乘以x


  • 对进制数组、哈希值数组的处理:
p[0]=1;//无第0位,赋值为1是为了方便后续运算
for(int i=1;i<=n;i++)
{
	p[i]=p[i-1]*base;//每一位的进制都是前一位的进制乘以base(左移一位)
	h[i]=h[i-1]*base+s[i];//前i位的哈希值位前i-1位的哈希值乘以进制再加上当前位   
}

举例:
若输入的s为"ABCDEFG"
h[1]("A")的值为'A'
h[2]("AB")的值为"A"×base+'B'
h[3]("ABC")的值为"AB"×base+'C'
以此类推

  • 求子串的哈希值
ull shash(int l,int r)//求s中从l到r的子串的哈希值  
    return h[r]-h[l-1]*p[r-l+1];//从第1位到第r位的哈希值-从第1位到第l位的前一位的哈希值(乘以进制类似于填零补位)  

举例:若输入的s为"ABCDEFG" l为2,r为5
所以从l到r的子串为"BCDE"
h[r]为"ABCDE"
h[l-1]为"A"
如果直接相减肯定会有错位 如下所示
  ABCDE
-     A
————

所以应该给"A"补位 要补的位数就是p数组
p[r-l+1]=4
所以A应左移4位
  ABCDE
-   A
————
       BCDE
最后所得的结果就是"BCDE"

#include<bits/stdc++.h>
#define ull unsigned long long
#define N 500010
using namespace std;
ull p[N],h[N],flag;
ull b=233;
char s[N];
char ans[N];
int n;
ull shash(int l,int r)
{
	return h[r]-h[l-1]*p[r-l+1];
}
bool findpos(int pos)
{
	ull l,r;
	int mid=1+n>>1;
	if(pos==mid)
	{
		l=shash(1,mid-1);
		r=shash(mid+1,n);
	}
	else if(pos<mid)
	{
		l=shash(1,pos-1)*p[mid-pos]+shash(pos+1,mid);
		r=shash(mid+1,n);
	}
	else
	{
		l=shash(1,mid-1);
		r=shash(mid,pos-1)*p[n-pos]+shash(pos+1,n);
	}
	if(l==r&&flag!=l) 
	{
		flag=l;
		if(pos<=mid)
		{
			for(int i=mid+1;i<=n;i++)
				ans[i-mid]=s[i];
		}
		else 
		{
			for(int i=1;i<mid;i++)
				ans[i]=s[i];
		}
		return 1;
	}
	return 0;
}
int main()
{
	cin>>n>>s+1;
	p[0]=1;
	for(int i=1;i<=n;i++)
		p[i]=p[i-1]*b,h[i]=h[i-1]*b+s[i];
	if(n%2==0) 
	{
		cout<<"NOT POSSIBLE";
		return 0;
	}
	int cnt=0;
	for(int i=1;i<=n;i++)
	{
		cnt+=findpos(i);
		if(cnt>1)
		{
			cout<<"NOT UNIQUE";
			return 0;
		}
	}
	if(cnt==0) cout<<"NOT POSSIBLE";
	else cout<<ans+1; 
	return 0;
}

标签:shash,哈希,int,ull,字符串,进制
来源: https://www.cnblogs.com/rabbitohh/p/14882394.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有