[USACO17OPEN]Bovine Genomics G

二分+hash前缀和+set

P3667

二分是很显然的,那么 check 的过程是一个给字符串判等的过程,那么自然就会想到 hash :

hash(s)=i=1nsi·baseni

(也就是把字符串看成一个 base 进制数)

(一般会加一个模数,但实际上放着不管就相当于对 unsigned long long 的最大值取模了,效率更高风险更大,至少在这题没出什么锅)

这样的 hash ,用类似前缀和的思想存下到每一位的 hash 值之后,就可以做到 O(1) 查询子串的 hash 值:

hash(slr)=hash(sr)hash(sl1)·baserl+1

比如 base=10 时:

hash(s9)=123456789

hash(s5)=12345

hash(s69)=12345678912345·104=6789

(当然 base 要预处理 i 次幂)


二分答案长度,枚举每一个左端点,将前 n 个串的 hash 值存到 set 里,再遍历后 n 个字符串,如果某个字符串的 hash 值已在 set 里,说明有重复


一些让我luogu最优解第二的卡常小技巧:

  1. 读入字符串时,实测使用
cin.tie(0),ios::sync_with_stdio(0);

的cin比快读要快

  1. unordered_set 是无序的听起来会快很多,但也因此迭代的效率不如普通set,在此题中也是set稍快一点点

完整代码qwq:

#include<bits/stdc++.h>
#define EL puts("Elaina")
#define reg register int
#define qwq 0
using namespace std;
typedef unsigned long long ull;
const int maxn=5e2+3;
const ull base=5;
ull pw[maxn];
int val[137];
inline void init(){
    pw[0]=1,val['A']=1,val['C']=2,val['G']=3,val['T']=4;
    for(reg i=1;i<maxn;++i)
        pw[i]=pw[i-1]*base;
}
int n,m;
ull h[2][maxn][maxn];
char s[maxn];
inline void getHash(int p,int x){
    for(reg i=1;i<=m;++i)
        h[p][x][i]=h[p][x][i-1]*base+val[s[i]];
}
inline ull zStr(int p,int x,int l,int r){
    return h[p][x][r]-h[p][x][l-1]*pw[r-l+1];
}
inline bool check(int l,int r){
    set <ull> S;
    for(reg i=1;i<=n;++i){
        ull tmp=zStr(0,i,l,r);
        S.insert(tmp);
    }
    for(reg i=1;i<=n;++i){
        ull tmp=zStr(1,i,l,r);
        if(S.count(tmp))return 1;
    }
    return 0;
}
inline bool check(int len){
    for(reg l=1,r=len;r<=m;++l,++r)
        if(!check(l,r))return 1;
    return 0;
}
void solve(){
    cin>>n>>m;
    for(reg i=1;i<=n;++i)
        cin>>s+1,getHash(0,i);
    for(reg i=1;i<=n;++i)
        cin>>s+1,getHash(1,i);
	int l=0,r=m,mid,ans;
	while(l<=r){
		mid=(l+r)>>1;
		if(check(mid))ans=mid,r=mid-1;
		else l=mid+1;
	}
	printf("%d\n",ans);
}
int main(){
    cin.tie(qwq),ios::sync_with_stdio(qwq);
    init();
    solve();
    return qwq;
}
posted @   Muel_imj  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示