字符串专题

哈希

好用的哈希模数:

  • unsigned long long/long long 自然溢出
  • \(2654435769\)(存疑)
  • \(1610612741\)(极力推荐)
  • \(998244353\)\(10^9+7\)(经典,貌似容易被×)

提供一种 \(N\) 模数哈希的写法:

Luogu P3546

#include<bits/stdc++.h>
#define int long long
#define ll long long
#define fd(i,a,b) for(int i=a,_i=b;i<=_i;i=-~i)
#define bd(i,a,b) for(int i=a,_i=b;i>=_i;i=~-i)
using namespace std;

const int N=1e6+509,MT=1;

int n,m,f[N],ans,_L;
char s[N];

inline int read(){int x;scanf("%lld",&x);return x;}

inline void write(int x,int F=1)
{
	if(F==0) printf("%lld",x);
	else if(F==1) printf("%lld\n",x);
	else printf("%lld ",x);
}

struct My_Hash
{
	
	int mod=998244353,seed=131;
	int p[N],Pw[N];	
	
	inline int Hash(int l,int r) {return ((p[r]-p[l-1]*Pw[r-l+1]%mod+mod)%mod);}
	
	inline void Pre()
	{
		Pw[0]=1;
		fd(i,1,n)
		{
			p[i]=(p[i-1]*seed+s[i])%mod;
			Pw[i]=Pw[i-1]*seed%mod;
		}
	} 
	
	inline void Named(int _mod_,int _seed_)	{mod=_mod_,seed=_seed_;}
	
}H[MT+1];

inline bool Check_Diff(int l,int r,int L,int R)
{
	int Need=MT>3?MT-1:MT,Sum=0;
	fd(i,0,MT)
		if(H[i].Hash(l,r)!=H[i].Hash(L,R))
			Sum=-~Sum;
	if(Sum>Need) return 1;
	return 0;
}

inline bool Check_Same(int l,int r,int L,int R)
{
	fd(i,0,MT)
		if(H[i].Hash(l,r)!=H[i].Hash(L,R))
			return 0;
	return 1;
}

signed main()
{
	
#define FJ
#ifndef FJ
	freopen("bzoj1066_.in","r",stdin);
	freopen("bzoj1066_.out","w",stdout);
#endif
	
	n=read();m=n/2;
	scanf("%s",s+1);
	
	H[0].Named(2654435769,131);//存疑(good)
	H[1].Named(1610612741,131);//Good
	//998244353 1e9+7//貌似容易被×
	
//	貌似可以(这道题用这种方法可过):
//	srand(time(0));
//	fd(i,2,MT) H[i].Named((rand()%1000000000)*1000000000+rand()%1000000000,131);
	
	fd(i,0,MT) H[i].Pre();
	
	bd(i,m,0)
	{
		_L=min(_L+2,m-i);
		while(_L>0&&Check_Diff(i+1,i+_L,n-i-_L+1,n-i)) _L--;
		if(Check_Same(1,i,n-i+1,n)) ans=max(ans,i+_L);
	}
	
	write(ans);
	
	return 0;
	
}

另一种写法:

P3370 【模板】字符串哈希

#include<bits/stdc++.h>
#define int long long
#define ll long long
#define fd(i,a,b) for(int i=(a);i<=(b);i=-~i)
#define bd(i,a,b) for(int i=(a);i>=(b);i=~-i)
#define db(x) cout<<"DEBUG "<<#x<<" = "<<x<<endl;
#define endl '\n'
using namespace std;

//#define SIZE (1<<20)
//char In[SIZE],Out[SIZE],*p1=In,*p2=In,*p3=Out;
//#define getchar() (p1==p2&&(p2=(p1=In)+fread(In,1,SIZE,stdin),p1==p2)?EOF:*p1++)
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+(c-48);c=getchar();}
	return x*f;
}
template<typename _T>
inline void write(_T x)
{
	static _T sta[35];int top=0;
	if(x<0) putchar('-'),x=-x;
	do{sta[top++]=x%10,x/=10;}while(x);
	while(top) putchar(sta[--top]+'0');
}

template<int SIZ>
struct Hash
{
	int p=131,pw[SIZ+5],h[SIZ+5],len,Mod=1610612741;
	Hash(int _mod_=-1){Mod=(_mod_==-1)?Mod:_mod_;pw[0]=1;fd(i,1,SIZ)pw[i]=pw[i-1]*p%Mod;}
	inline void clear(){fd(i,1,len)h[i]=0;len=0;}
	inline int to(char c){return((c>='a'&&c<='z')?c-'a':((c>='A'&&c<='Z')?c-'A'+26:c-'0'+52));}
	inline void pre(char s[]){len=strlen(s+1);fd(i,1,len) h[i]=(h[i-1]*p%Mod+to(s[i]))%Mod;}
	inline int H(int l=1,int r=-1){if(r==-1) r=len;return (h[r]-h[l-1]*pw[r-l+1]%Mod+Mod)%Mod;}
};

const int N=1e6+509,M=1e6+509,mod=998244353;

set<int> f;
int n;
char s[N];

signed main()
{
//#define FJ
#ifdef FJ
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
#else
//	freopen("A.in","r",stdin);
//	freopen("A.out","w",stdout);
#endif
//#define io
#ifdef io
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
#endif
	
	srand(time(0));
	const int _mod_=rand()*rand();
	Hash<N> has(_mod_);
	
	n=read();
	fd(i,1,n)
	{
		scanf("%s",s+1);
		has.pre(s);
		f.insert(has.H());
		has.clear();
	}
	printf("%lld",f.size());
	
	return 0;
}
posted @ 2024-07-15 20:09  whrwlx  阅读(10)  评论(0编辑  收藏  举报