zoukankan      html  css  js  c++  java
  • BZOJ_4892_[Tjoi2017]dna_哈希

    BZOJ_4892_[Tjoi2017]dna_哈希

    Description

    加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S,有这个序列的碱基序列就会表现出喜欢吃藕的
    性状,但是研究人员发现对碱基序列S,任意修改其中不超过3个碱基,依然能够表现出吃藕的性状。现在研究人员
    想知道这个基因在DNA链S0上的位置。所以你需要统计在一个表现出吃藕性状的人的DNA序列S0上,有多少个连续子
    串可能是该基因,即有多少个S0的连续子串修改小于等于三个字母能够变成S。

    Input

    第一行有一个数T,表示有几组数据 每组数据第一行一个长度不超过10^5的碱基序列S0
    每组数据第二行一个长度不超过10^5的吃藕基因序列S

    Output

    共T行,第i行表示第i组数据中,在S0中有多少个与S等长的连续子串可能是表现吃藕性状的碱基序列

    Sample Input

    1
    ATCGCCCTA
    CTTCA

    Sample Output

    2
     
    分析:
    枚举S0中每个与S等长的子串。我们求三次S和当前子串的lcp(最长公共前缀)来确定S0是否能够修改小于等于3个字母变成S。
    lcp求法:二分加哈希
     
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 100050
    #define LL unsigned long long
    int T, l1, l2;
    char s1[N], s2[N];
    LL mi[N], p = 19260817, h1[N], h2[N];
    bool check(int x) {
    	int i = x, j = 1;
    	int l = 1, r = l2 + 1, mid;
    	for(int k = 1;k <= 3; ++ k) {
    		while(l < r) {
    			mid = (l + r) >> 1;
    			if(h1[i + mid - 1] - h1[i - 1] * mi[mid] == h2[j + mid - 1] - h2[j - 1] * mi[mid]) l = mid + 1;
    			else r = mid;
    		}
    		i = i + l; j = j + l;
    		l = 1, r = l2 - j + 2;
    		if(j > l2) return 1;
    		mid = l2 - j + 1;
    		if(h1[i + mid - 1] - h1[i - 1] * mi[mid] == h2[j + mid - 1] - h2[j - 1] * mi[mid]) return 1;
    	}
    	return 0;
    }
    int main() {
    	scanf("%d", &T);
    	while(T -- ) {
    		int i, ans = 0;
    		scanf("%s%s", s1 + 1, s2 + 1);
    		l1 = strlen(s1 + 1);
    		l2 = strlen(s2 + 1);
    		if(l1 < l2) {
    			puts("0"); continue;
    		}
    		mi[0] = 1;
    		for(i = 1;i <= l1; ++ i) {
    			mi[i] = mi[i - 1] * p;
    			h1[i] = h1[i - 1] * p + s1[i];
    		}
    		for(i = 1;i <= l2; ++ i) h2[i] = h2[i - 1] * p + s2[i];
    		for(i = 1;i <= l1 - l2 + 1; ++ i) {
    			if(check(i)) ans++;
    		}
    		printf("%d
    ", ans);
    	}
    }
    
     
  • 相关阅读:
    websocket使用nginx作为反向代理
    curl模拟http发送get或post接口测试
    linux tail -f messages查看控制台失败
    shell中使用>/dev/null 2>&1 丢弃信息
    mysql备份与还原
    计算机中RAM和ROM
    *C语言有关指针的变量声明中的几个易错点
    五种存储变量补充~作用域和存储时期
    typedef和#define的简单比较
    fopen()函数参数
  • 原文地址:https://www.cnblogs.com/suika/p/8672067.html
Copyright © 2011-2022 走看看