[洛谷P3763] [TJOI2017]DNA
洛谷题目链接:[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的更多相关文章
- 洛谷P3763 [Tjoi2017]DNA 【后缀数组】
题目链接 洛谷P3763 题解 后缀数组裸题 在BZOJ被卡常到哭QAQ #include<algorithm> #include<iostream> #include< ...
- 洛谷P3763 [TJOI2017]DNA(后缀数组 RMQ)
题意 题目链接 Sol 这题打死我也不会想到后缀数组的,应该会全程想AC自动机之类的吧 但知道这题能用后缀数组做之后应该就不是那么难了 首先把\(S\)和\(S0\)拼到一起跑,求出Height数组 ...
- 洛谷P3763 [TJOI2017]DNA(后缀自动机)
传送门 好像用SAM写的很少诶…… 其实我一开始也没想到要用SAM的……主要是没有想到找的时候可以dfs…… 首先建一个SAM,然后跑一遍dfs,枚举一下下一位,如果相同直接继续,否则就花费一次次数来 ...
- [洛谷P3761] [TJOI2017]城市
洛谷题目链接:[TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速 ...
- 洛谷P3759 [TJOI2017]不勤劳的图书管理员 【树状数组套主席树】
题目链接 洛谷P3759 题解 树状数组套主席树板题 #include<algorithm> #include<iostream> #include<cstring> ...
- P3763 [TJOI2017]DNA
链接:https://www.luogu.org/problemnew/show/P3763 题解: 挺水的一题后缀数组 枚举每一个开头用后缀数组判断能否在3次内匹配完
- 洛谷P3760 - [TJOI2017]异或和
Portal Description 给出一个\(n(n\leq10^5)\)的序列\(\{a_n\}(\Sigma a_i\leq10^6)\),求该数列所有连续和的异或和. Solution 线段 ...
- 洛谷P3759 - [TJOI2017]不勤劳的图书管理员
Portal Description 给出一个\(1..n(n\leq5\times10^4)\)的排列\(\{a_n\}\)和数列\(\{w_n\}(w_i\leq10^5)\),进行\(m(m\l ...
- 洛谷P3758 - [TJOI2017]可乐
Portal Description 给出一张\(n(n\leq30)\)个点\(m(m\leq100)\)条边的无向图.初始时有一个可乐机器人在点\(1\),这个机器人每秒会做出以下三种行为之一:原 ...
随机推荐
- C#操作Excel执行分类多条件汇总合并
之前发了一片模拟合并,详见模拟Excel同一列相同值的单元格合并 在之前的文章中介绍了思想,其中Excel采用的二维数组模拟,今天花了点时间,学习了一下C#操作Excel,实现了类似的效果! 准备 需 ...
- iOS-AFNetworking与ASIHTTPRequest的区别
一.底层实现 1.AFN的底层实现基于OC的NSURLConnection和NSURLSession 2.ASI的底层实现基于纯C语言的CFNetwork框架 3.因为NSURLConnectio ...
- JS中的数组转变成JSON格式字符串的方法
有一个JS数组,如: var arr = [["projectname1","projectnumber1"],["projectname2" ...
- 3dContactPointAnnotationTool开发日志(二十)
为了使工具更人性化,我又在每个status的text上绑了个可以拖拽实现值改变的脚本,但是不知道为啥rotx那个值越过+-90范围后连续修改就会产生抖动的现象,试了很多方法也没能弄好,不过实际用起 ...
- hadoop下安装mysql
http://www.cnblogs.com/zhuyp1015/p/3561470.html 第一步:先把这个文件放入到linux环境下桌面. 接着编写脚本:sudo apt-get u ...
- python 查看趴下来的数据
#coding=utf-8 import re from lxml import etree import requests def requests_view(response): import w ...
- 织梦dede:list标签在列表页同一文章显示两次的解决方法
在列表页用{dede:list}标签调用文章的时候出现了同一篇文章显示两次的问题,经过一天的奋战最后终于解决了,下面CMS集中营站长简单说下我的解决过程来供各位学友参考:1.怀疑是不是每次添加都会自动 ...
- foreach循环2
<select id="test" parameterType="java.util.List" resultType="user"& ...
- hash 默认使用equal进行元素比较 防止元素重复
hash 默认使用equal进行元素比较 防止元素重复
- 【bzoj2763】[JLOI2011]飞行路线 分层图最短路
题目描述 Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的 ...