zoukankan      html  css  js  c++  java
  • UVALive4671

    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
    ",++TT,v.size());
    	}
    	return 0;
    }
    
  • 相关阅读:
    java并发编程的艺术笔记-第二章
    java并发编程的艺术笔记-第一章
    Class字节码的加载
    Maven学习笔记(1)
    深入分析java web技术内幕读书笔记-第一章
    VMware虚拟机扩展内存和磁盘
    【避坑】for循环删除列表元素的注意事项--remove函数逆序删除
    虚拟机无法上网问题解决
    jmeter变量跨线程组使用--设置全局变量
    常见慢查询原因
  • 原文地址:https://www.cnblogs.com/Troverld/p/12757272.html
Copyright © 2011-2022 走看看