LGP3318题解

看完题后第一眼:是不是要 trie 子树和什么的东西啊。

第二眼:哦好像直接大力哈希就行了。

对于长的那边,把长度 ls+lt/2 的部分和剩下的部分做匹配(不应该叫匹配吧其实,反正就是循环之后可以对的上(?))。

然后把匹配位置求出来后对于每个匹配成功的位置,对剩下的位置做 Hash,然后丢个桶数一数就好了。

复杂度 \(O(n+m)\) 随便乱草。

#include<cstdio>
const int M=4000005,mod=1145141923,MOD=1000003;
int n,m,ls,lt,l1,l2,pw[M];long long ans;char*s[M],*t[M];int S[M];
inline void swap(char&a,char&b){
	char c=a;a=b;b=c;
}
inline void swap(int&a,int&b){
	int c=a;a=b;b=c;
}
struct HashTable{
	int cnt,h[MOD];
	struct Node{
		int key,num,nx;
	}t[M];
	inline void Ins(const int&key){
		int&H=h[key%MOD];for(int E=H;E;E=t[E].nx)if(t[E].key==key)return void(++t[E].num);
		t[++cnt]=(Node){key,1,H};H=cnt;
	}
	inline int Qry(const int&key){
		for(int E=h[key%MOD];E;E=t[E].nx)if(t[E].key==key)return t[E].num;return 0;
	}
}Hash;
inline int hash(const int&L,const int&R){
	return(S[R]+1ll*(mod-pw[R-L+1])*S[L-1])%mod;
}
signed main(){
	scanf("%d%d%d%d",&n,&m,&ls,&lt);pw[0]=1;pw[1]=13331;for(int i=2;i<=ls||i<=lt;++i)pw[i]=13331ll*pw[i-1]%mod;
	if(ls<lt){
		for(int i=1;i<=n;++i)t[i]=new char[ls+1],scanf("%s",t[i]+1);
		for(int i=1;i<=m;++i)s[i]=new char[lt+1],scanf("%s",s[i]+1);
		for(int i=1;i<=n;++i)for(int j=1;(j<<1|1)<ls;++j)swap(s[i][j],s[i][ls-j+1]);
		for(int i=1;i<=m;++i)for(int j=1;(j<<1|1)<lt;++j)swap(t[i][j],t[i][lt-j+1]);
		swap(ls,lt);swap(n,m);
	}
	else{
		for(int i=1;i<=n;++i)s[i]=new char[ls+1],scanf("%s",s[i]+1);
		for(int i=1;i<=m;++i)t[i]=new char[lt+1],scanf("%s",t[i]+1);
	}
	l1=ls+lt>>1;l2=ls-l1;
	for(int i=1;i<=m;++i){
		int H(0);for(int k=1;k<=lt;++k)H=(13331ll*H+(t[i][k]^96))%mod;Hash.Ins(H);
	}
	for(int i=1;i<=n;++i){
		for(int k=1;k<=ls;++k)S[k]=(13331ll*S[k-1]+(s[i][k]^96))%mod;
		const int&H=hash(l1+1,ls);
		for(int k=1;k<=l1;++k){
			if(k+l2-1<=l1){
				if(hash(k,k+l2-1)==H){
					ans+=Hash.Qry((1ll*hash(k+l2,l1)*pw[k-1]+hash(1,k-1))%mod);
				}
			}
			else{
				if((1ll*hash(k,l1)*pw[l2-(l1-k+1)]+hash(1,l2-(l1-k+1)))%mod==H){
					ans+=Hash.Qry(hash(l2-(l1-k+1),k));
				}
			}
		}
	}
	printf("%lld",ans);
}
posted @ 2022-07-16 14:44  Prean  阅读(13)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};