https://www.luogu.org/problemnew/show/P3763

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

是的这篇代码过不了BZOJ(因为懒得卡了/不想写SAM/不会DC3……众多原因)

其实容错三次匹配并不吓人,我们可以先跳跃匹配到匹配不上的地方,然后cnt++,继续跳跃……直到匹配完全或者cnt>3为止。

这个跳跃完全可以枚举起点,然后用SA来求lcp进而实现跳跃匹配以此变成$O(n)$的。

所以总复杂度是$O(Tnlogn)$的……只要卡卡就能过洛谷。

当然为了过BZOJ,要么常数优秀(写SAM,然后遍历,每次选择一个节点往下走,如果和当前节点匹配不上则cnt++,匹配复杂度不变但是常数小),要么就学DC3,要么……其实后缀数组卡卡也能过。

  1. #include<map>
  2. #include<cmath>
  3. #include<stack>
  4. #include<queue>
  5. #include<cstdio>
  6. #include<cctype>
  7. #include<vector>
  8. #include<cstdlib>
  9. #include<cstring>
  10. #include<iostream>
  11. #include<algorithm>
  12. using namespace std;
  13. typedef long long ll;
  14. const int N=2e5+;
  15. inline int turn(char ch){
  16. if(ch==)return ;
  17. if(ch=='A')return ;
  18. if(ch=='G')return ;
  19. if(ch=='C')return ;
  20. if(ch=='T')return ;
  21. return ;
  22. }
  23. char s[N],p[N];
  24. int n,rk[N],height[N],w[N],sa[N];
  25. inline bool pan(int *x,int i,int j,int k){
  26. int ti=i+k<n?x[i+k]:-;
  27. int tj=j+k<n?x[j+k]:-;
  28. return ti==tj&&x[i]==x[j];
  29. }
  30. void SA_init(){
  31. int *x=rk,*y=height,r=;
  32. for(int i=;i<r;i++)w[i]=;
  33. for(int i=;i<n;i++)w[turn(s[i])]++;
  34. for(int i=;i<r;i++)w[i]+=w[i-];
  35. for(int i=n-;i>=;i--)sa[--w[turn(s[i])]]=i;
  36. r=;x[sa[]]=;
  37. for(int i=;i<n;i++)
  38. x[sa[i]]=s[sa[i]]==s[sa[i-]]?r-:r++;
  39. for(int k=;r<n;k<<=){
  40. int yn=;
  41. for(int i=n-k;i<n;i++)y[yn++]=i;
  42. for(int i=;i<n;i++)
  43. if(sa[i]>=k)y[yn++]=sa[i]-k;
  44. for(int i=;i<r;i++)w[i]=;
  45. for(int i=;i<n;i++)w[x[y[i]]]++;
  46. for(int i=;i<r;i++)w[i]+=w[i-];
  47. for(int i=n-;i>=;i--)sa[--w[x[y[i]]]]=y[i];
  48. swap(x,y);r=;x[sa[]]=;
  49. for(int i=;i<n;i++)
  50. x[sa[i]]=pan(y,sa[i],sa[i-],k)?r-:r++;
  51. }
  52. }
  53. void height_init(){
  54. int i,j,k=;
  55. for(int i=;i<=n;i++)rk[sa[i]]=i;
  56. for(int i=;i<n;i++){
  57. if(k)k--;
  58. int j=sa[rk[i]-];
  59. while(s[i+k]==s[j+k])k++;
  60. height[rk[i]]=k;
  61. }
  62. }
  63. int f[N][],lg[N];
  64. inline int qpow(int a){return <<a;}
  65. void st_init(){
  66. for(int i=;i<=n;i++){
  67. f[i-][]=height[i];
  68. lg[i]=lg[i-];
  69. if((<<lg[i]+)==i)lg[i]++;
  70. }
  71. for(int j=;j<=lg[n];j++){
  72. for(int i=;i<n;i++){
  73. if(i+qpow(j)->=n)break;
  74. f[i][j]=min(f[i][j-],f[i+qpow(j-)][j-]);
  75. }
  76. }
  77. }
  78. int lcp(int i,int j){
  79. int l=rk[i],r=rk[j];if(l>r)swap(l,r);
  80. l--;r--;if(r<)return ;l++;
  81. int len=r-l+,k=lg[len],h=qpow(k);
  82. return min(f[l][k],f[r-h+][k]);
  83. }
  84. int main(){
  85. int t;scanf("%d",&t);
  86. while(t--){
  87. scanf("%s%s",s,p);
  88. n=strlen(s);int m=strlen(p);
  89. s[n++]='#';
  90. for(int i=;i<m;i++)s[n++]=p[i];
  91. s[n++]=;SA_init();n--;height_init();st_init();
  92. int ans=;
  93. for(int i=;i<n-*m;i++){
  94. int cnt=;
  95. for(int j=;j<m&&cnt<=;){
  96. if(s[i+j]!=s[n-m+j])cnt++,j++;
  97. else j+=lcp(i+j,n-m+j);
  98. }
  99. if(cnt<=)ans++;
  100. }
  101. printf("%d\n",ans);
  102. }
  103. return ;
  104. }

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

洛谷3763:[TJOI2017]DNA——题解的更多相关文章

  1. [洛谷P3763] [TJOI2017]DNA

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

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

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

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

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

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

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

  5. 洛谷P2832 行路难 分析+题解代码【玄学最短路】

    洛谷P2832 行路难 分析+题解代码[玄学最短路] 题目背景: 小X来到了山区,领略山林之乐.在他乐以忘忧之时,他突然发现,开学迫在眉睫 题目描述: 山区有n座山.山之间有m条羊肠小道,每条连接两座 ...

  6. 【洛谷P3960】列队题解

    [洛谷P3960]列队题解 题目链接 题意: Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有 n×m ...

  7. 洛谷P2312 解方程题解

    洛谷P2312 解方程题解 题目描述 已知多项式方程: \[a_0+a_1x+a_2x^2+\cdots+a_nx^n=0\] 求这个方程在 \([1,m]\) 内的整数解(\(n\) 和 \(m\) ...

  8. 洛谷P1577 切绳子题解

    洛谷P1577 切绳子题解 题目描述 有N条绳子,它们的长度分别为Li.如果从它们中切割出K条长度相同的 绳子,这K条绳子每条最长能有多长?答案保留到小数点后2位(直接舍掉2为后的小数). 输入输出格 ...

  9. 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)

    洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...

  10. 洛谷 P1220 关路灯 题解

    Description 有 $n$ 盏路灯,每盏路灯有坐标(单位 $m$)和功率(单位 $J$).从第 $c$ 盏路灯开始,可以向左或向右关闭路灯.速度是 $1m/s$.求所有路灯的最少耗电.输入保证 ...

随机推荐

  1. WPF DataGridRow Event

    CM(Caliburn.Micro)框架绑定DataGridRow事件 <DataGrid.ItemContainerStyle> <Style TargetType="D ...

  2. Ubuntu16.04比较好的一系列软件安装介绍

    https://blog.csdn.net/Gerald_Jones/article/details/80784976

  3. OSG-漫游

    本文转至http://www.cnblogs.com/shapherd/archive/2010/08/10/osg.html 作者写的比较好,再次收藏,希望更多的人可以看到这个文章 互联网是是一个相 ...

  4. Vue动画效果

    1.哪些元素/那些组件适合在那些条件下实现动画效果 条件渲染 (使用 v-if) 条件展示 (使用 v-show) 动态组件 组件根节点 简单经典例子:(文字隐藏到显示效果) <div> ...

  5. HADOOP-输出数据实体类承载

    新建一个bean包: 1.实现Writerable 2.有一个空的构造方法 代码实现: import java.io.DataInput; import java.io.DataOutput; imp ...

  6. ionic 获取input的值

    1.参数传递法 例子:获取input框内容 这里有个独特的地方,直接在input处使用 #定义参数的name值,注意在ts中参数的类型 在html页面中 <ion-input type=&quo ...

  7. 讯飞云 API 语音听写 python3 调用例程

    #!/usr/bin/python3 # -*- coding: UTF-8 -*- import requests import time import gzip import urllib imp ...

  8. parity 注记词

    spousal tint untold around rosy daintily unrated sheep choice showpiece chirping gala

  9. 基于Hadoop2.5.0的集群搭建

    http://download.csdn.net/download/yameing/8011891 一. 规划 1.  准备安装包 JDK:http://download.oracle.com/otn ...

  10. Mybatis ResultMap(2)

    SQL 映射XML 文件是所有sql语句放置的地方.需要定义一个workspace,一般定义为对应的接口类的路径.写好SQL语句映射文件后,需要在MyBAtis配置文件mappers标签中引用,例如: ...