题目描述

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

输入输出格式

输入格式:

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

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

输出格式:

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

输入输出样例

输入样例#1: 复制

1
ATCGCCCTA
CTTCA
输出样例#1: 复制

2

说明

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

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

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

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

 #include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
typedef long long ll;
using namespace std; const int N=;
int n,m,T,ans,x[N],y[N],sa[N],log[N],c[N],rk[N],h[N],st[N][];
char s[N],s1[N],S[N]; int Cmp(int a,int b,int l){ return y[a]==y[b] && y[a+l]==y[b+l]; } void build(int m){
memset(y,,sizeof(y));
rep(i,,m) c[i]=;
rep(i,,n) c[x[i]]++;
rep(i,,m) c[i]+=c[i-];
for (int i=n; i; i--) sa[c[x[i]]--]=i;
for (int k=,p=; p<n; k<<=,m=p){
p=;
rep(i,n-k+,n) y[++p]=i;
rep(i,,n) if (sa[i]>k) y[++p]=sa[i]-k;
rep(i,,m) c[i]=;
rep(i,,n) c[x[y[i]]]++;
rep(i,,m) c[i]+=c[i-];
for (int i=n; i; i--) sa[c[x[y[i]]]--]=y[i];
rep(i,,n) y[i]=x[i]; p=; x[sa[]]=;
rep(i,,n) x[sa[i]]=Cmp(sa[i-],sa[i],k) ? p : ++p;
}
} void get(){
int k=;
rep(i,,n) rk[sa[i]]=i;
rep(i,,n){
for (int j=sa[rk[i]-]; i+k<=n && j+k<=n && S[i+k]==S[j+k]; k++);
h[rk[i]]=k; if (k) k--;
}
} void rmq(){
rep(i,,n) st[i][]=h[i];
rep(i,,log[n])
rep(j,,n-(<<i)+) st[j][i]=min(st[j][i-],st[j+(<<(i-))][i-]);
} int ask(int l,int r){
if (l>r) swap(l,r);
l++; int t=log[r-l+];
return min(st[l][t],st[r-(<<t)+][t]);
} int main(){
log[]=; rep(i,,N-) log[i]=log[i>>]+;
for (scanf("%d",&T); T--; ){
scanf("%s",s+); scanf("%s",s1+);
int n0=strlen(s+),n1=strlen(s1+);
rep(i,,n0) S[i]=s[i]; S[strlen(s+)+]='$';
rep(i,,n1) S[strlen(s+)+i+]=s1[i];
n=n0+n1+;
rep(i,,n) x[i]=(int)S[i];
build(); get(); rmq(); ans=;
rep(i,,n0-n1+){
int a=i,b=n0+,f=;
rep(j,,){
int t=ask(rk[a],rk[b]);
if (b+t>n) { f=; break; }
if (i+t>n0) break;
a+=t+; b+=t+;
}
if (f) ans++;
}
printf("%d\n",ans);
}
return ;
}

[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. 【BZOJ】2099: [Usaco2010 Dec]Letter 恐吓信

    [题意]给定长度为n和m的两个字符串S和T,要求在字符串S中取出若干段拼成T(可重复取),求最小段数,n,m<=50000. [算法]后缀自动机 || 后缀数组 [题解]对串S建SAM,然后在上 ...

  2. 关于linux下crontab mysql备份出来的数据为0字节的问题

    问题出在计划任务所执行的脚本上! 脚本中的调用的指令应该都写全路径~ 实例: # crontab -c 编辑下的内容 30 18 * * * /root/backup.sh 意思为:每天18:30执行 ...

  3. JS 判断手机操作系统代码

    还是利用UA, 返回值: ios, android, unknown function getMobileType () { var ua = window.navigator.userAgent.t ...

  4. weblogic性能监控

    1.

  5. mysq配置

    mysql运维 1.mysql配置文件:/etc/my.cnf mysql日记文件 :安装时候配置的,可以通过ps aux|grep mysqld 查询 ps aux|grep mysqld mysq ...

  6. mysql安装后开启远程

    操作系统为centos7 64 1.修改 /etc/my.cnf,在 [mysqld] 小节下添加一行:skip-grant-tables=1 这一行配置让 mysqld 启动时不对密码进行验证 2. ...

  7. Linux实用命令之xdg-open

    为什么要介绍 xdg-open 呢,得先从需求说起. 一般在控制台中,可以使用命令操作各式文本文件.但难以避免,需要操作一些非文本文件,如 pdf,doc 等. 此时,一般的做法是,打开文件管理器,再 ...

  8. Linux内核中的Cache段

    Linux内核中的Cache段 原文地址:http://blogold.chinaunix.net/u2/85263/showart_1743693.html 最近移植LEON3的内核时,了解了一些简 ...

  9. Android: 在onCreate()中获得对象尺寸

    onCreate() 中 View 尚未绘制完成 很多时候,我们需要在某个界面刚刚加载的时候,执行一些对 View 进行操作的代码,通常我们把这些代码放在 Activity 的 onCreate() ...

  10. HDU 1217 Arbitrage(Bellman-Ford判断负环+Floyd)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1217 题目大意:问你是否可以通过转换货币从中获利 如下面这组样例: USDollar 0.5 Brit ...