ICode9

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

字符串基础:hash,kmp,trie

2022-09-03 19:34:43  阅读:183  来源: 互联网

标签:hash trie void int kmp 字符串 now 失配


三个很基础的板子放到一块。发现原来没有位置放了于是现开一个。

  1. Hash

hash的思想是把一个字符串拍成一个数存储,这样就能快速比较两个字符串是否相同。

大概的方法:

  1. 我们选取一个合适的进制数(比如131这样的质数)和一个较大的模数。
  2. 将这个字符串看作一个p进制数(因为每个字符都是有数字大小的)
  3. 如果这个数过大就取个模。
    具体的实现很简单。
void gethash(){
	int len=strlen(s+1);p[0]=1;
	for(int i=1;i<=strlen(s+1);i++){
		p[i]=1ll*p[i-1]*prime%mod;
		hs[i]=(1ll*hs[i-1]*prime+s[i])%mod;
	}
}
int gethash(int l,int r){
	return (hs[r]-1ll*hs[l-1]*p[r-l+1]%mod+mod)%mod;
}

2.kmp(看毛片)

大概是一个不断跳失配指针的\(O(n)\)字符串匹配算法。举个例子,我们要求字符串s在字符串t中的所有出现位置。

首先我们要求出s的失配指针。首先我们定义border是即是s的前缀又是s的后缀(当然不能是s自己)的最长串。

我们可以通过暴力跳的方式求出s的所有border位置。具体地说,让s与自己匹配,如果失配就跳到当前的border指针上,直到匹配或者跳空。

匹配同样暴力跳。

void getnxt(char s[]){
	int n=strlen(s+1);
	nxt[1]=0;
	for(int i=2,j=0;i<=n;i++){
		while(j&&s[i]!=s[j+1])j=nxt[j];//失配 跳指针 
		if(s[i]==s[j+1])j++;//匹配到 更新指针位置 
		nxt[i]=j;
	}
}
void search(char s[],char t[]){
	int n=strlen(s+1),m=strlen(t+1),ans=0;
	for(int i=1,j=0;i<=m;i++){
		while(j&&t[i]!=s[j+1])j=nxt[j];//同样的 匹配时如果失配就跳指针 
		if(t[i]==s[j+1])j++;
		f[i]=j;//匹配到就更新最长匹配s的多少长度的前缀 
		if(j==n)ans[++ans[0]]=i;
	}
}

然后是trie。这个也很简单,按照前缀的顺序搞棵树出来。这个不太好说。上图的话比较简洁,但是我应该不至于这个都搞个图。

void ins(char s[]){
	int p=0,len=strlen(s);
	for(int i=0;i<len;i++){
		if(!trie[p][s[i]-'a']){
			trie[p][s[i]-'a']=++cnt;//如果当前节点没有这个字母就新建节点 
		}
		p=trie[p][s[i]-'a'];//往儿子跳 
	}cnt[p]++;//标记一下结尾 
}
int search(char s[]){
	int p=0,len=strlen(s);
	for(int i=0;i<len;i++){
		if(!trie[p][s[i]-'a'])return 0;
		p=trie[p][s[i]-'a'];//同样暴力从树上往下跳 
	}
	return cnt[p];
}

trie的另一个应用:01trie。

我们发现(不管是谁发现的反正我没发现)trie的性质可以让它很好地维护异或最大值这种东西。具体地说,我们把int变量拆成31个二进制位扔到trie上。然后每次求异或最大值的时候从上往下跳,有不同跳不同。

void ins(int x){
	int now=0;
	for(int i=30;i>=0;i--){
		int w=(x>>i)&1;
		if(!trie[now][w])trie[now][w]=++cnt;//把当前位拆开上树 
		now=trie[now][w];
	}
}
int query(int x){
	int now=0,ans=0;
	for(int i=30;i>=0;i--){
		int w=(x>>i)&1;ans<<=1;
		if(trie[now][!w]){
			now=trie[now][!w];
			ans+=!w;//如果有不同就不同 
		}else{
			now=trie[now][w];
			ans+=w;
		}
	}
	return ans;
}

标签:hash,trie,void,int,kmp,字符串,now,失配
来源: https://www.cnblogs.com/gtm1514/p/16653350.html

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

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

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

ICode9版权所有