hash处理字符串问题

1 判断字符串是否相等

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
const int mod=1000000007;	//mod为计算hash值时的模数 
const int p=10000019;		//p为计算hash值时的进制数 
vector<int> ans;

//字符串hash
long long hashFunc(string str){
	long long h=0;
	for(int i=0;i<str.length();i++){
		h=(h*p+str[i]-'a')%mod;
	}
	return h;
} 

int main(){
	string str;
	while(getline(cin,str),str!="#"){
		long long id=hashFunc(str);
		ans.push_back(id);
	}
	sort(ans.begin(),ans.end());
	int count=0;
	for(int i=0;i<ans.size();i++){
		if(i==0||ans[i]!=ans[i-1]){
			count++;
		}
	}
	cout<<count<<endl;
	return 0;
}

2 判断两个字符串中的子串是否相等

#include<iostream>
#include<cstdio>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;

const ll mod=1000000007;	//mod为计算hash值时的模数 
const ll p=10000019;		//p为计算hash值时的进制数 
const ll maxn=1010;			//maxn为字符串最长长度
//powP[i]存放p^i%mod,H1和H2分别存放str1和str2的hash值
ll powP[maxn],H1[maxn]={0},H2[maxn]={0};
//pr1存放str1的所有<子串hash值,子串长度>,pr2同理
vector<pair<int,int> >pr1,pr2;

//init函数初始化powP函数
void init(int len){
	powP[0]=1;
	for(int i=1;i<=len;i++){
		powP[i]=powP[i-1]*p%mod;
	} 
}

//calH函数计算字符串str的hash值
void calH(ll H[],string &str){
	H[0]=str[0];
	for(int i=1;i<str.length();i++){
		H[i]=(H[i-1]*p+str[i])%mod;
	}
}

//calSingleSubH计算H[i...j]
int calSingleSubH(ll H[],int i,int j){
	if(i==0) return H[j];
	else return ((H[j]-H[i-1]*powP[j-i+1])%mod+mod)%mod;
}

//calSubH计算所有子串的hash值,并将<子串hash值,子串长度>存入pr
void calSubH(ll H[],int len,vector<pair<int,int>>&pr){
	for(int i=0;i<len;i++){
		for(int j=i;j<len;j++){
			int hashValue=calSingleSubH(H,i,j);
			pr.push_back(make_pair(hashValue,j-i+1));
		}
	}
}

//计算pr1和pr2中相同的hash值,维护最大长度
int getMax(){
	int ans=0;
	for(int i=0;i<pr1.size();i++){
		for(int j=0;j<pr2.size();j++){
			if(pr1[i].first==pr2[j].first)
				ans=max(ans,pr1[i].second);
		}
	}
	return ans;
}

int main(){
	string str1,str2;
	getline(cin,str1);
	getline(cin,str2);
	init(max(str1.length(),str2.length()));
	calH(H1,str1);
	calH(H2,str2);
	calSubH(H1,str1.length(),pr1);
	calSubH(H2,str2.length(),pr2);
	printf("ans = %d\n",getMax());
	return 0;
}

3 回文字符串(二分法)

#include<iostream>
#include<stdio.h>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1000000007;	//mod为计算hash值时的模数 
const ll p=10000019;		//p为计算hash值时的进制数 
const ll maxn=200010;		//maxn为字符串最长长度
//powP[i]存放p^i%mod,H1和H2分别存放str和rstr的hash值
ll powP[maxn],H1[maxn],H2[maxn];

//init函数初始化powP函数
void init(){
	powP[0]=1;
	for(int i=1;i<maxn;i++)
		powP[i]=(powP[i-1]*p)%mod;
} 

//calH函数计算字符串str的hash值
void calH(ll H[],string &str){
	H[0]=str[0];
	for(int i=1;i<str.length();i++){
		H[i]=(H[i-1]*p+str[i])%mod;
	}
} 

//calSingleSubH计算H[i...j] 
int calSingleSubH(ll H[],int i,int j){
	if(i==0) return H[j];
	return ((H[j]-H[i-1]*powP[j-i+1])%mod+mod)%mod;
}

//对称点为i,字符串长len,在[l,r]里二分回文半径
//寻找最后一个满足条件“hashL==hashR”的回文半径
//等价于寻找第一个满足条件"hashL!=hashR"的回文半径,然后减1即可 
//isEven当求奇回文时为0,当求偶回文时为1 
int binarySearch(int l,int r,int len,int i,int isEven){
	while(l<r){
		int mid=(l+r)/2;
		int H1L=i-mid+isEven,H1R=i;
		int H2L=len-1-(i+mid),H2R=len-1-(i+isEven);
		int hashL=calSingleSubH(H1,H1L,H1R);
		int hashR=calSingleSubH(H2,H2L,H2R);
		if(hashL!=hashR) r=mid;
		else l=mid+1; 
	}
	return l-1;	//返回最大回文半径 
} 

int main(){
	init();
	string str;
	getline(cin,str);
	calH(H1,str);
	reverse(str.begin(),str.end());
	calH(H2,str);
	int ans=0;
	//奇回文
	for(int i=0;i<str.length();i++){
		//二分上界为分界点i的左右长度的较小值加1
		int maxLen=min(i,(int)str.length()-1-i)+1; 
		int k=binarySearch(0,maxLen,str.length(),i,0);
		ans=max(ans,k*2+1);
	} 
	//偶回文
	for(int i=0;i<str.length();i++){
		int maxLen=min(i+1,(int)str.length()-1-i)+1;
		int k=binarySearch(0,maxLen,str.length(),i,1);
		ans=max(ans,k*2);
	} 
	printf("%d\n",ans);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值