zoukankan      html  css  js  c++  java
  • 【题解】Bovine Genomics G奶牛基因组(金)

    查看原题请戳这里

    首先,这道题让求最大值最小,于是我们就很自然得想到了去二分这个最小值。

    那么,怎么check呢?

    我们发现,如果直接暴力去check,即二分区间长度+暴力枚举字符串+暴力枚举区间左端点+暴力对比,那么时间复杂度是O(n2m2log2n)O(n^2m^2log_2n)的。(引人深思的复杂度……)

    很显然,我们需要去优化这个时间复杂度。

    首先,如果我们对要进行对比的区间进行哈希,然后用set进行判断,就可以将时间复杂度降低到O(nm2log22n)O(nm^2log_2^2n)

    这里提供两种用set去检验的思路:

    1. 用一个set去记录好的基因有多少不同的哈希值cnt1cnt1,再用一个set去记录坏的基因有多少不同的哈希值cnt2cnt2,再用一个set去记录好的基因和坏的基因一共有多少不同的哈希值cnt3cnt3,如果cnt3cnt1=cnt2cnt3-cnt1=cnt2,那么好的基因的哈希值和坏的基因的哈希值没有重复。
    2. 用一个set去储存好的基因的哈希值,然后用set自带的find函数查询每一个坏的基因的哈希值是否在这个集合中出现过。

    但是,即便如此,我们的时间复杂度依然无法通过这道题,主要原因是每次记录哈希值都占用了大量的时间。
    hash[i]hash[j1]×priij+1(i>j)hash[i]-hash[j-1] imes pri^{i-j+1}(i>j)快速求得hash[i][j]hash[i][j]的值。

    时间复杂度:O(nmlog2n)O(nmlog_2 n)

    code:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #define ll long long
    #define INF 0x7fffffff
    #define re register
    #define rep(i,a,b) for(int i = (a); i <= (b); i++)
    #define qwq printf("qwq
    ");
    #define mod1 122420729
    #define mod2 131937371
    
    using namespace std;
    
    int read()
    {
    	register int x = 0,f = 1;register char ch;
    	ch = getchar();
    	while(ch > '9' || ch < '0'){if(ch == '-') f = -f;ch = getchar();}
    	while(ch <= '9' && ch >= '0'){x = x * 10 + ch - 48;ch = getchar();}
    	return x * f;
    }
    
    int n,m,l,r,mid,cnt1,cnt2,cnt3;
    
    long long hfg[505][505],hfb[505][505],a[505],b[505],c[505];
    
    char good[505][505],bad[505][505];
    
    void Hash()
    {
    	memset(hfg,0,sizeof(hfg));
    	memset(hfb,0,sizeof(hfb));
    	for(register int i = 0; i < n; i++) hfg[i][0] = good[i][0];
    	for(register int i = 0; i < n; i++) hfb[i][0] = bad[i][0];
    	for(register int i = 0; i < n; i++)
    		for(register int j = 1; j < m; j++)
    			hfg[i][j] = hfg[i][j - 1] * 13331 + good[i][j];
    	for(register int i = 0; i < n; i++)
    		for(register int j = 1; j < m; j++)
    			hfb[i][j] = hfb[i][j - 1] * 13331 + bad[i][j];
    }
    
    void get_Hash(int s,int l)
    {
    	if(s == 0)
    	{
    		for(int i = 0; i < n; i++) a[i] = hfg[i][l - 1];
    		for(int i = 0; i < n; i++) b[i] = hfb[i][l - 1];
    		return ;
    	}
    	for(int i = 0; i < n; i++) a[i] = hfg[i][s + l - 1] - hfg[i][s - 1] * c[l];
    	for(int i = 0; i < n; i++) b[i] = hfb[i][s + l - 1] - hfb[i][s - 1] * c[l];
    }
    
    set<int> se1,se2,se3;
    
    bool check(int l)
    {
    	for(register int i = 0; i + l - 1 < m; i++)
    	{
    		get_Hash(i,l);
    		int flag = 1;
    		se1.clear(); se2.clear(); se3.clear();
    		for(register int j = 0; j < n; j++) se1.insert(a[j]),se3.insert(a[j]);
    		cnt1 = se1.size();
    		for(register int j = 0; j < n; j++) se2.insert(b[j]),se3.insert(b[j]);
    		cnt2 = se2.size();
    		if(se3.size() - cnt1 == cnt2) return true;
    	}
    	return false;
    }
    
    int main()
    {
    	n = read(); m = read();
    	c[1] = 13331;
    	for(int i = 2; i <= m; i++) c[i] = c[i - 1] * 13331; 
    	for(register int i = 0; i < n; i++) cin >> good[i];
    	for(register int i = 0; i < n; i++) cin >> bad[i];
    	l = 1; r = m;
    	Hash();
    	while(l < r)
    	{
    		mid = (l + r) >> 1;
    		if(check(mid)) r = mid;
    		else l = mid + 1;
    	}
    	
    	get_Hash(1,4);
    	printf("%d
    ",r);
        return 0;
    }
    
    
  • 相关阅读:
    linux centos7 防止暴力破解
    win10 配置git 环境变量
    Tengine的说明
    php composer 报错 requires php ^7.1.8 || ^8.0 -> your php version
    uni-app v-for循环遍历 动态切换class、动态切换style
    Tomcat安装与配置
    我的云服务之WWW
    RHEL7 单独安装图形 X11
    python3-sql解析库——sqlparse
    Python3实战——爬虫入门
  • 原文地址:https://www.cnblogs.com/aurorapolaris/p/13449111.html
Copyright © 2011-2022 走看看