UVALive4671 - K-neighbor substrings

IV.UVALive4671 - K-neighbor substrings

因为是\(AB\)串,所以我们之前II.残缺的字符串的式子中\(t_i-s_i\)的值只有可能为\(-1,0,1\)。这样的话,直接平方后,判别式给出的结果就是题目中的‘Hamming distance’,即不同字符数。

但是,这题相同的子串是只能计入一次的。我们就暴力哈希去个重完事。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const double pi=acos(-1);
const int lg=18,lim=(1<<lg);
int TT,k,S,T,ss,st[lim+10],p[lim+10],rev[lim+10];
ull srd=19260817,pov[lim+10];
char s[lim+10],t[lim+10];
struct cp{
	double x,y;
	cp(double u=0,double v=0){x=u,y=v;}
	friend cp operator +(const cp &u,const cp &v){return cp(u.x+v.x,u.y+v.y);}
	friend cp operator -(const cp &u,const cp &v){return cp(u.x-v.x,u.y-v.y);}
	friend cp operator *(const cp &u,const cp &v){return cp(u.x*v.x-u.y*v.y,u.x*v.y+u.y*v.x);}
}f[lim+10],g[lim+10];
void FFT(cp *a,int tp){
	for(int i=0;i<lim;i++)if(i<rev[i])swap(a[i],a[rev[i]]);
	for(int md=1;md<lim;md<<=1){
		cp rt=cp(cos(pi/md),tp*sin(pi/md));
		for(int stp=md<<1,pos=0;pos<lim;pos+=stp){
			cp w=cp(1,0);
			for(int i=0;i<md;i++,w=w*rt){
				cp x=a[pos+i],y=w*a[pos+md+i];
				a[pos+i]=x+y;
				a[pos+md+i]=x-y;
			}
		}
	}
}
struct HASH{
	ull val;
	int len;
	HASH(){
		val=0ull;
		len=0;
	}
	HASH(char ip){
		val=ip-'a';
		len=1;
	}
	friend HASH operator +(const HASH &x,const HASH &y){
		HASH z;
		z.val=x.val*pov[y.len]+y.val;
		z.len=x.len+y.len;
		return z;
	}
	friend HASH operator -(const HASH &x,const HASH &y){
		HASH z;
		z.val=x.val-y.val*pov[x.len-y.len];
		z.len=x.len-y.len;
		return z;
	}
	friend HASH operator ==(const HASH &x,const HASH &y){
		if(x.len!=y.len)return false;
		if(x.val!=y.val)return false;
		return true;
	}
}hs[lim+10];
vector<ull>v;
int main(){
	pov[0]=1;
	for(int i=0;i<lim;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1));
	for(int i=1;i<lim;i++)pov[i]=pov[i-1]*srd;
	while(scanf("%d",&k)){
		if(k==-1)break;
		scanf("%s%s",t,s),S=strlen(s),T=strlen(t),ss=0,v.clear(),reverse(s,s+S);
		for(int i=0;i<lim;i++)f[i]=g[i]=cp(0,0);
		for(int i=0;i<S;i++)ss+=(s[i]-'a')*(s[i]-'a');
		for(int i=0;i<T;i++){
			st[i]=(t[i]-'a')*(t[i]-'a');
			hs[i]=HASH(t[i]);
			if(i)st[i]+=st[i-1],hs[i]=hs[i-1]+hs[i];
		}
		for(int i=0;i<S;i++)f[i]=cp(s[i]-'a',0);
		for(int i=0;i<T;i++)g[i]=cp(t[i]-'a',0);
		FFT(f,1),FFT(g,1);
		for(int i=0;i<lim;i++)f[i]=f[i]*g[i];
		FFT(f,-1);
		for(int i=S-1;i<T;i++){
			p[i]=ss+st[i]-2*(int)(f[i].x/lim+0.5);
			if(i>=S)p[i]-=st[i-S];
			if(p[i]<=k){
				if(i>=S)v.push_back((hs[i]-hs[i-S]).val);
				else v.push_back(hs[i].val);
			}
		}
		sort(v.begin(),v.end()),v.resize(unique(v.begin(),v.end())-v.begin());
		printf("Case %d: %d\n",++TT,v.size());
	}
	return 0;
}
posted @ 2020-04-22 22:13  Troverld  阅读(106)  评论(0编辑  收藏  举报