ICode9

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

字符串串基础——字符串Hash,KMP,Trie树

2022-07-23 20:04:25  阅读:130  来源: 互联网

标签:Hash Trie ll long int 字符串 hash define


终于来到了我最不想学的字符串

字符串Hash

原理

把字符串看做 \(b\) 进制数,把字符串 \(S\) 映射成一个函数 \(hash(S)\) ,即一个数字,便于比较

$ hash(S) = (S_1b^{n-1}+ S_2b^{n-2}+\dots+S_n)\pmod p $

计算 \(hash\) 函数的时间复杂度是 \(O(\mid S\mid)\) ,这里一般选 \(233\) 作为进制, \(10^9+7\) , \(10^9+9\) ,\(10^9+21\) 作为模数

如果在处理字符串子串 \(hash\) 值的时候再计算时间复杂度就会飙升到 \(O(n^2)\)

所以我们可以将字符串的前缀 \(hash\) 预处理出来,用时 \(O(1)\) 查询即可(原理为把高位消掉)

例题

乌力波

题意:给定两个串 \(W,T\) 求 \(W\) 在 \(T\) 中出现的次数

模板题

点击查看代码
#include<bits/stdc++.h>
#define N 1000005
#define b 233
#define mod 1000000021
#define ll long long
using namespace std;

int q;
ll hashw,hashs[N],p[N];
inline string getstr();
ll gethash(int l,int r);
 
int main(){
	cin>>q;
	p[0]=1;
	for(int i=1;i<=N-2;i++)
		p[i]=p[i-1]*b%mod;
	while(q--){
		int ans=0;
		string w,t;
		w=getstr();t=getstr();
		int wlen=w.size(),tlen=t.size();
		hashw=0;
		for(int i=0;i<wlen;i++)
			hashw=(hashw*b+w[i])%mod;
		hashs[0]=t[0];
		for(int i=1;i<tlen;i++)
			hashs[i]=(hashs[i-1]*b+t[i])%mod;
		for(int i=0;i+wlen-1<tlen;i++)
			if(hashw==gethash(i,i+wlen-1))	
				ans++;
		printf("%d\n",ans);
	} 
}

inline string getstr(){
	char ch=getchar();
	string s="";
	while(ch==' '||ch=='\n')
		ch=getchar();
	while(ch!=' '&&ch!='\n')
		s+=ch,ch=getchar();
	return s;
}

ll gethash(int l,int r){
	return (hashs[r]-hashs[l-1]*p[r-l+1]%mod+mod)%mod;
}

P3667 [USACO17OPEN]Bovine Genomics G

二分+ \(hash\)
枚举左端点,然后对于长度二分答案,先把 \(B\) 串的 \(hash\) 值先排个序,然后对于 \(A\) 串的每个 \(hash\) 值,二分查找然后判断是否相等即可

还需要注意的一点是这道题答案的单调性有所不同,对于有解的情况有最小值而不是最大值

点击查看代码
#include<bits/stdc++.h>
#define N 505
#define B 233
#define ll long long
using namespace std;

const ll mod=1e9+21;
int n,m,ans=N+100;
ll p[N],hash_suma[N][N],hash_sumb[N][N];
string a[N],b[N];
inline string getstr();
inline ll gethasha(int i,int l,int r);
inline ll gethashb(int i,int l,int r);

int main(){
//	freopen("P3667_2.in","r",stdin);
	cin>>n>>m;
	p[0]=1;
	for(int i=1;i<=N-2;i++)
		p[i]=p[i-1]*B%mod;
	for(int i=1;i<=n;i++)
		a[i]=getstr();
	for(int i=1;i<=n;i++)
		b[i]=getstr();
	for(int i=1;i<=n;i++){
		hash_suma[i][0]=a[i][0];
		hash_sumb[i][0]=b[i][0];
		for(int j=1;j<m;j++){
			hash_suma[i][j]=(hash_suma[i][j-1]*B+a[i][j])%mod;
			hash_sumb[i][j]=(hash_sumb[i][j-1]*B+b[i][j])%mod;
		}
	}
	for(int i=0;i<m;i++){
		int l=1,r=m-i;
		int t=605;
		while(l<=r){
			int mid=(l+r)>>1;
			int j=i+mid-1;
			bool flag=false;
			ll tmp[n+5];
			for(int k=1;k<=n;k++)
				tmp[k]=gethashb(k,i,j);
			sort(tmp+1,tmp+n+1);
			for(int k=1;k<=n;k++){
				int temp=lower_bound(tmp+1,tmp+1+n,gethasha(k,i,j))-tmp;
				if(tmp[temp]==gethasha(k,i,j)){
					flag=true;
					break;
				}
			}
			if(flag) l=mid+1;
			else{
				t=min(t,mid);
				r=mid-1;
			}
		}
		if(t) ans=min(ans,t);
	}
	cout<<ans;
} 

inline string getstr(){
	char ch=getchar();
	string s="";
	while(ch==' '||ch=='\n')
		ch=getchar();
	while(ch!=' '&&ch!='\n')
		s+=ch,ch=getchar();
	return s;
}

inline ll gethasha(int i,int l,int r){
	return (hash_suma[i][r]-hash_suma[i][l-1]*p[r-l+1]%mod+mod)%mod;
}

inline ll gethashb(int i,int l,int r){
	return (hash_sumb[i][r]-hash_sumb[i][l-1]*p[r-l+1]%mod+mod)%mod;
}

标签:Hash,Trie,ll,long,int,字符串,hash,define
来源: https://www.cnblogs.com/Rolling-star/p/16512869.html

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

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

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

ICode9版权所有