题目描述

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

输入输出格式

输入格式:

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

每组数据第二行一个长度不超过10^5的吃藕基因序列S

输出格式:

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

输入输出样例

输入样例#1: 复制

  1. 1
  2. ATCGCCCTA
  3. CTTCA
输出样例#1: 复制

  1. 2

说明

对于20%的数据,S0,S的长度不超过10^4

对于20%的数据,S0,S的长度不超过10^5,0<T<=10

两个串连起来中间插个特殊字符然后后缀数组求四次LCP即可。

启示:永远不要低估SA模板的默写难度。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #define rep(i,l,r) for (int i=l; i<=r; i++)
  5. typedef long long ll;
  6. using namespace std;
  7.  
  8. const int N=;
  9. int n,m,T,ans,x[N],y[N],sa[N],log[N],c[N],rk[N],h[N],st[N][];
  10. char s[N],s1[N],S[N];
  11.  
  12. int Cmp(int a,int b,int l){ return y[a]==y[b] && y[a+l]==y[b+l]; }
  13.  
  14. void build(int m){
  15. memset(y,,sizeof(y));
  16. rep(i,,m) c[i]=;
  17. rep(i,,n) c[x[i]]++;
  18. rep(i,,m) c[i]+=c[i-];
  19. for (int i=n; i; i--) sa[c[x[i]]--]=i;
  20. for (int k=,p=; p<n; k<<=,m=p){
  21. p=;
  22. rep(i,n-k+,n) y[++p]=i;
  23. rep(i,,n) if (sa[i]>k) y[++p]=sa[i]-k;
  24. rep(i,,m) c[i]=;
  25. rep(i,,n) c[x[y[i]]]++;
  26. rep(i,,m) c[i]+=c[i-];
  27. for (int i=n; i; i--) sa[c[x[y[i]]]--]=y[i];
  28. rep(i,,n) y[i]=x[i]; p=; x[sa[]]=;
  29. rep(i,,n) x[sa[i]]=Cmp(sa[i-],sa[i],k) ? p : ++p;
  30. }
  31. }
  32.  
  33. void get(){
  34. int k=;
  35. rep(i,,n) rk[sa[i]]=i;
  36. rep(i,,n){
  37. for (int j=sa[rk[i]-]; i+k<=n && j+k<=n && S[i+k]==S[j+k]; k++);
  38. h[rk[i]]=k; if (k) k--;
  39. }
  40. }
  41.  
  42. void rmq(){
  43. rep(i,,n) st[i][]=h[i];
  44. rep(i,,log[n])
  45. rep(j,,n-(<<i)+) st[j][i]=min(st[j][i-],st[j+(<<(i-))][i-]);
  46. }
  47.  
  48. int ask(int l,int r){
  49. if (l>r) swap(l,r);
  50. l++; int t=log[r-l+];
  51. return min(st[l][t],st[r-(<<t)+][t]);
  52. }
  53.  
  54. int main(){
  55. log[]=; rep(i,,N-) log[i]=log[i>>]+;
  56. for (scanf("%d",&T); T--; ){
  57. scanf("%s",s+); scanf("%s",s1+);
  58. int n0=strlen(s+),n1=strlen(s1+);
  59. rep(i,,n0) S[i]=s[i]; S[strlen(s+)+]='$';
  60. rep(i,,n1) S[strlen(s+)+i+]=s1[i];
  61. n=n0+n1+;
  62. rep(i,,n) x[i]=(int)S[i];
  63. build(); get(); rmq(); ans=;
  64. rep(i,,n0-n1+){
  65. int a=i,b=n0+,f=;
  66. rep(j,,){
  67. int t=ask(rk[a],rk[b]);
  68. if (b+t>n) { f=; break; }
  69. if (i+t>n0) break;
  70. a+=t+; b+=t+;
  71. }
  72. if (f) ans++;
  73. }
  74. printf("%d\n",ans);
  75. }
  76. return ;
  77. }

[BZOJ4892][TJOI2017]DNA(后缀数组)的更多相关文章

  1. [TJOI2017]DNA --- 后缀数组

    [TJOI2017]DNA 题目描述 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S, 有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其中不超过3个 ...

  2. [TJOI2017] DNA - 后缀数组,稀疏表

    [TJOI2017] DNA Description 求模式串与主串的匹配次数,容错不超过三个字符. Solution 枚举每个开始位置,进行暴力匹配,直到失配次数用光或者匹配成功.考虑到容错量很小, ...

  3. 洛谷P3763 [TJOI2017]DNA(后缀数组 RMQ)

    题意 题目链接 Sol 这题打死我也不会想到后缀数组的,应该会全程想AC自动机之类的吧 但知道这题能用后缀数组做之后应该就不是那么难了 首先把\(S\)和\(S0\)拼到一起跑,求出Height数组 ...

  4. bzoj4892 [TJOI2017]DNA

    bzoj4892 [TJOI2017]DNA 给定一个匹配串和一个模式串,求模式串有多少个连续子串能够修改不超过 \(3\) 个字符变成匹配串 \(len\leq10^5\) hash 枚举子串左端点 ...

  5. BZOJ.4892.[TJOI2017]DNA(后缀自动机/后缀数组)

    题目链接 \(Description\) 给出两个串\(S,T\),求\(T\)在\(S\)中出现了多少次.出现是指.可以有\(3\)次(\(3\)个字符)不匹配(修改使其匹配). \(Solutio ...

  6. BZOJ4892:[TJOI2017]dna(hash)

    Description 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S,有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其中不超过3个碱基,依然能够表 ...

  7. BZOJ4892 Tjoi2017dna(后缀数组)

    对每个子串暴力匹配至失配三次即可.可以用SA查lcp.然而在bzoj上被卡常了.当然也可以二分+哈希或者SAM甚至FFT. #include<iostream> #include<c ...

  8. 【BZOJ4892】DNA(后缀数组)

    [BZOJ4892]DNA(后缀数组) 题面 BZOJ 洛谷 题解 看到这道题目,我第一反应是\(FFT\)??? 然后大力码出了一个\(FFT\) 就像这样 #include<iostream ...

  9. 洛谷P3763 [Tjoi2017]DNA 【后缀数组】

    题目链接 洛谷P3763 题解 后缀数组裸题 在BZOJ被卡常到哭QAQ #include<algorithm> #include<iostream> #include< ...

随机推荐

  1. 【leetcode 简单】第四题 罗马数字转整数

    罗马数字包含以下七种字符:I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 写做 II ,即为两个并列 ...

  2. android Timer TimerTask用法笔记

    Android中经常会遇到执行一些周期性定时执行的任务.初学的时候经常会使用Thread.sleep()方法.在android中,有Timer可以专门干这个事情. 先看看Timer.class中都是些 ...

  3. Fiddler -工具使用介绍(附:拦截请求并修改返回数据)(转)

    一.Fiddler 介绍 Fiddler 是一个使用 C# 编写的 http 抓包工具.它使用灵活,功能强大,支持众多的 http 调试任务,是 web.移动应用的开发调试利器. 1,功能特点 同 H ...

  4. 一. Jmeter--使用代理录制脚本

    Jmeter脚本是以.JMX格式为主 1. Jmeter也是支持录制的,支持第三方录制方式和代理录制方式. (1).第三方录制主要是通过badboy来录制,录制后另存为jmx格式即可. (2).Jme ...

  5. Ubuntu10.04 下安装RabbitVCS

    安装RabbitVCS的方法步骤如下: 1.sudo add-apt-repository ppa:rabbitvcs/ppa       #将rabbitvcs的添加到源里面.(次操作会提示是否要添 ...

  6. Linux下如何打开img镜像文件

    有些镜像文件为IMG格式,在Linux如何打开呢?例如从微软dreampark下载的Windows Server 2008 R2镜像文件,使用file命令查看: $ file chs_windows_ ...

  7. 64_t3

    texlive-dice-svn28501.0-33.fc26.2.noarch.rpm 24-May-2017 15:52 36490 texlive-dichokey-doc-svn17192.0 ...

  8. 002利用zabbix监控某个目录大小

    近期,因为JMS的消息堆积导致ApacheMQ频率故障(消息没有被消费掉,导致其数据库达到1.2G,JMS此时直接挂掉),很是郁闷!刚好自 己在研究zabbix.既然zabbix如此强大,那么它可以监 ...

  9. php cache类代码(php数据缓存类)

    如果访问量大的话会给数据库造成很大的负担,所以对于变化不经常的内容要做好php 数据cache(缓存)是十分必要的,我做了一个简单的php“文件缓存”的类,希望对大家有所帮助. 思路是这样的: 对于一 ...

  10. Oracle Spatial操作geometry方法

    Oracle Spatial中SDO_GEOMETRY类型: CREATE TYPE SDO_GEOMETRY AS OBJECT( SDO_GTYPE NUMBER,--几何类型,如点线面 SDO_ ...