BZOJ 4084 [Sdoi2015]双旋转字符串

题解:hash

至今不会unsigned long long 的输出

把B扔进map

找A[mid+1][lenA]在A[1][mid]中的位置

把A[1][mid]贴两遍(套路)

枚举A[mid+1][lenA]在A[1][mid]中出现的位置,把其他位置的hash值求出来,在map里查有多少符合的B串

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
const int maxn=8000009;
typedef unsigned long long uLint;

int n,m,lenA,lenB,mid;
char s[maxn];
long long ans;

int r;
uLint h[maxn];
uLint fac[maxn];
map<uLint,int>ma;
uLint a[maxn];
void Addstring(){
	int cnt=0;
	uLint midstring=0;
	for(int i=mid+1;i<=lenA;++i)midstring=midstring*233+s[i];
	
	for(int i=1;i<=mid;++i)s[i+mid]=s[i];
	
	h[0]=0;
	for(int i=1;i<=mid+mid;++i)h[i]=h[i-1]*233+s[i];
	for(int i=1;i<=mid;++i){
		uLint tm=h[i+r-1]-h[i-1]*fac[r];
		if(tm!=midstring)continue;
		a[++cnt]=h[i+mid-1]-h[i+r-1]*fac[mid-r];
	}
	sort(a+1,a+1+cnt);
	cnt=unique(a+1,a+1+cnt)-a-1;
	for(int i=1;i<=cnt;++i)ma[a[i]]++;
}

int main(){
	scanf("%d%d%d%d",&n,&m,&lenA,&lenB);
	fac[0]=1;
	for(int i=1;i<=lenA+lenA;++i)fac[i]=fac[i-1]*233;
	mid=(lenA+lenB)>>1;
	r=lenA-mid;
	
	while(n--){
		scanf("%s",s+1);
		Addstring();
	}
	while(m--){
		scanf("%s",s+1);
		uLint tm=0;
		for(int i=1;i<=lenB;++i)tm=tm*233+s[i];
		ans=ans+ma[tm];
	}
	cout<<ans<<endl;
	return 0;
}

  

posted @ 2018-03-04 18:54  ws_zzy  阅读(235)  评论(0编辑  收藏  举报