zoukankan      html  css  js  c++  java
  • [TJOI2017]DNA --- 后缀数组

    [TJOI2017]DNA

    题目描述

    加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S,

    有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其中不超过3个碱基,依然能够表现出吃藕的性状。

    现在研究人员想知道这个基因在DNA链(S_{0})上的位置。

    所以你需要统计在一个表现出吃藕性状的人的DNA序列(S_{0})上,有多少个子串可能是该基因,

    即有多少个(S_{0})的子串修改小于等于三个字母能够变成S。

    输入输出格式

    输入格式:

    第一行有一个数T,表示有几组数据

    每组数据第一行一个长度不超过(10^{5})的碱基序列(S_{0})

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

     

    输出格式:

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

     

    输入输出样例

    输入样例#1: 
     
    1
    ATCGCCCTA
    CTTCA
     
    输出样例#1: 
     
    2
     

    说明

    对于20%的数据,(S_{0}),S的长度不超过(10^{4})

    对于20%的数据,(S_{0}),S的长度不超过(10^{5}),0<T<=10

     

    作为后缀数组的模板集成题来做的。

    首先考虑一个比较容易想到的事情.

    (S_{0})大串中存在长度和(S)相同的串只有(n)个

    因此只要一个一个暴力判断就好了。

    怎么判断快一点??

    比如串'ACGAC'和串'ACAAC'

    前面的'AC'相同,因此可以直接调用。

    到了'G'和'A'不同,来一个(tim)计数器表示失配了几次,此时,(tim++)

    接下了后面的'AC'相同,因此这个子串和模式串只有一处不同。

    可以发现,每当(tim<=3)匹配完成一次时,(ans++)

    那么,怎么得到'AC'相同这个过程??

    用后缀数组的LCP或者哈希二分LCP或后缀树跑LCP即可

     

    后缀数组复杂度(O(n log n + n * 6)) = (O(n log n))

    代码在此

  • 相关阅读:
    Java 第十一届 蓝桥杯 省模拟赛 洁净数
    Java 第十一届 蓝桥杯 省模拟赛 第十层的二叉树
    Java 第十一届 蓝桥杯 省模拟赛 第十层的二叉树
    Java 第十一届 蓝桥杯 省模拟赛 第十层的二叉树
    Java 第十一届 蓝桥杯 省模拟赛 70044与113148的最大公约数
    Java 第十一届 蓝桥杯 省模拟赛 70044与113148的最大公约数
    20. Valid Parentheses
    290. Word Pattern
    205. Isomorphic Strings
    71. Simplify Path
  • 原文地址:https://www.cnblogs.com/reverymoon/p/8955438.html
Copyright © 2011-2022 走看看