洛谷题目链接:[TJOI2017]DNA

题目描述

加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列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

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

题意: 问字符串\(s\)中有多少个长度为\(n0\)的连续的子串与字符串\(s0\)的不同在\(3\)个以内.


题解: 考虑在\(s\)中枚举字符串的起点,如果当前枚举到的位置与\(s0\)中的对应位置相同的话,就向后延伸它们的\(lcp\)的长度.如果不相同,就计数器加\(1\),继续向后枚举,如果枚举长度超过\(s0\)的长度\(n0\)了,说明这次枚举的起点合法.

求\(lcp\)的过程可以用哈希预处理二分长度的方法在\(O(logn)\)的时间内求出,也可以后缀数组预处理在\(O(1)\)的时间内求出.

用后缀数组预处理主要是用到了这个性质:\(lcp(suffix(sa[i]),suffix(sa[j]))=min\{height[k]\}(i<j,k\in[i,j])\)

这样就可以在求出\(height\)数组的情况下用倍增预处理出一段连续排名的\(height\)数组的最小值,然后\(O(1)\)查询了.

#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 2e5+5; int T, n, n0, m, sa[N], rk[N], sec[N], buk[N], height[N], f[25][N], Log[N], ans = 0;
char s[N], s0[N]; void rsort(){
for(int i = 0; i <= m; i++) buk[i] = 0;
for(int i = 1; i <= n; i++) buk[rk[i]]++;
for(int i = 1; i <= m; i++) buk[i] += buk[i-1];
for(int i = n; i >= 1; i--) sa[buk[rk[sec[i]]]--] = sec[i];
} void SuffixArray(){
for(int i = 1; i <= n; i++) rk[i] = s[i], sec[i] = i;
m = 260; rsort(); int num = 0;
for(int l = 1; l <= n && num < n; l <<= 1){
num = 0;
for(int i = 1; i <= l; i++) sec[++num] = n-l+i;
for(int i = 1; i <= n; i++) if(sa[i] > l) sec[++num] = sa[i]-l;
rsort(); swap(rk, sec), rk[sa[1]] = num = 1;
for(int i = 2; i <= n; i++)
rk[sa[i]] = (sec[sa[i]] == sec[sa[i-1]] && sec[sa[i]+l] == sec[sa[i-1]+l]) ? num : ++num;
m = num;
}
} void get_height(){
int j, k = 0;
for(int i = 1; i <= n; i++){
if(k) k--;
j = sa[rk[i]-1];
while(s[i+k] == s[j+k]) k++;
height[rk[i]] = k;
}
} void init(){
for(int i = 1; i <= n; i++) f[0][i] = height[i];
for(int j = 1; j <= 20; j++)
for(int i = 1; i+(1<<j)-1 <= n+n0; i++)
f[j][i] = min(f[j-1][i], f[j-1][i+(1<<(j-1))]);
} int lcp(int x, int y){
x = rk[x], y = rk[y]; if(x > y) swap(x, y);
x++;int lg = Log[y-x+1];
return min(f[lg][x], f[lg][y-(1<<lg)+1]);
} void clear(){
memset(f, 0x3f, sizeof(f));
ans = 0;
} int main(){
cin >> T; Log[0] = -1;
for(int i = 1; i <= 200000; i++) Log[i] = Log[i>>1]+1;
while(T--){
cin >> (s+1) >> (s0+1), n = strlen(s+1), n0 = strlen(s0+1);
for(int i = 1; i <= n0; i++) s[i+n] = s0[i]; n += n0;
SuffixArray(), get_height(), init();
for(int i = 1; i <= n-n0*2+1; i++){
int cnt = 0;
for(int j = 1; j <= n0 && cnt <= 3; j++){
if(s[i+j-1] != s[n-n0+j]) cnt++;
else j += lcp(i+j-1, n-n0+j)-1;
}
if(cnt <= 3) ans++;
}
cout << ans << endl;
clear();
}
return 0;
}

[洛谷P3763] [TJOI2017]DNA的更多相关文章

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

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

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

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

  3. 洛谷P3763 [TJOI2017]DNA(后缀自动机)

    传送门 好像用SAM写的很少诶…… 其实我一开始也没想到要用SAM的……主要是没有想到找的时候可以dfs…… 首先建一个SAM,然后跑一遍dfs,枚举一下下一位,如果相同直接继续,否则就花费一次次数来 ...

  4. [洛谷P3761] [TJOI2017]城市

    洛谷题目链接:[TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速 ...

  5. 洛谷P3759 [TJOI2017]不勤劳的图书管理员 【树状数组套主席树】

    题目链接 洛谷P3759 题解 树状数组套主席树板题 #include<algorithm> #include<iostream> #include<cstring> ...

  6. P3763 [TJOI2017]DNA

    链接:https://www.luogu.org/problemnew/show/P3763 题解: 挺水的一题后缀数组 枚举每一个开头用后缀数组判断能否在3次内匹配完

  7. 洛谷P3760 - [TJOI2017]异或和

    Portal Description 给出一个\(n(n\leq10^5)\)的序列\(\{a_n\}(\Sigma a_i\leq10^6)\),求该数列所有连续和的异或和. Solution 线段 ...

  8. 洛谷P3759 - [TJOI2017]不勤劳的图书管理员

    Portal Description 给出一个\(1..n(n\leq5\times10^4)\)的排列\(\{a_n\}\)和数列\(\{w_n\}(w_i\leq10^5)\),进行\(m(m\l ...

  9. 洛谷P3758 - [TJOI2017]可乐

    Portal Description 给出一张\(n(n\leq30)\)个点\(m(m\leq100)\)条边的无向图.初始时有一个可乐机器人在点\(1\),这个机器人每秒会做出以下三种行为之一:原 ...

随机推荐

  1. 软工实践Alpha冲刺(3/10)

    队名:我头发呢队 组长博客 作业博客 杰(组长) 过去两天完成了哪些任务 继续翻阅Google Material Design 2的官方文档 接下来的计划 音源爬取 还剩下哪些任务 app开发 燃尽图 ...

  2. TCP 的有限状态机

    TCP 有限状态机的图中每一个方框都是 TCP 可能具有的状态. 每个方框中的大写英文字符串是 TCP 标准所使用的 TCP 连接状态名. 状态之间的箭头表示可能发生的状态变迁. 箭头旁边的字,表明引 ...

  3. <Effective C++>读书摘要--Designs and Declarations<一>

    <Item 18> Make interfaces easy to use correctly and hard to use incorrectly 1.That being the c ...

  4. PHP给图片添加图片水印

    涉及到的函数: 1.file_get_contents():用于将文件的内容读入到一个字符串中的首选方法.如果操作系统支持,还会使用内存映射技术来增强性能. 2.list():list() 函数用于在 ...

  5. 【Json】Newtonsoft.Json高级用法

    手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数 ...

  6. 【bzoj1708】[USACO2007 Oct]Money奶牛的硬币 背包dp

    题目描述 在创立了她们自己的政权之后,奶牛们决定推广新的货币系统.在强烈的叛逆心理的驱使下,她们准备使用奇怪的面值.在传统的货币系统中,硬币的面值通常是1,5,10,20或25,50,以及100单位的 ...

  7. hadoop中DataNode消失挂掉的原因及解决方法

    昨天在进行Hadoop实验时遇到一个问题,在sbin目录下输入jps命令,查看当前节点的状态时,意外发现DataNode节点不见了!!于是回忆了一下自己之前的操作过程,大概是因为将自己进入文件夹,将某 ...

  8. CentOS 访问控制列表(tcp wrappers)

    1.TCP Wrappers是一个工作在应用层的安全工具,它只能针对某些具体的应用或者服务起到一定的防护作用.比如说ssh.telnet.FTP等服务的请求,都会先受到TCP Wrappers的拦截. ...

  9. 2015 EC L - Multiplication Table

    /************************************************************************* > File Name: L.cpp > ...

  10. BZOJ4003:[JLOI2015]城池攻占——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4003 https://www.luogu.org/problemnew/show/P3261 小铭 ...