[TJOI2017] DNA - 后缀数组,稀疏表
[TJOI2017] DNA
Description
求模式串与主串的匹配次数,容错不超过三个字符。
Solution
枚举每个开始位置,进行暴力匹配,直到失配次数用光或者匹配成功。考虑到容错量很小,所以每个位置开始的匹配过程中大部分与普通匹配是同样操作,而我们需要的其实就是 LCP 长度,所以预处理出后缀数组和高度数组,建 ST 表支持 RMQ 询问,来加速暴力匹配的过程。时间复杂度 \(O(n \log n)\)
#include <bits/stdc++.h>
using namespace std;
int n,k,l0,m=256,sa[250005],y[250005],u[250005],v[250005],o[250005],r[250005],h[250005],T;
char str[250005];
int lg2[250005];
struct clsst {
int a[250005][21];
void build(int *src,int n) {
for(int i=1;i<=n;i++) a[i][0]=src[i];
for(int i=1;i<=20;i++)
for(int j=1;j<=n-(1<<i)+1;j++)
a[j][i]=min(a[j][i-1],a[j+(1<<(i-1))][i-1]);
}
int query(int l,int r) {
if(l>r) swap(l,r);
int j=lg2[r-l+1];
return min(a[l][j],a[r-(1<<j)+1][j]);
}
} st;
int lcp(clsst *st,int p,int q)
{
if(r[p]>r[q]) swap(p,q);
return st->query(r[p]+1,r[q]);
}
int match(clsst *st,int p,int q)
{
return lcp(st,p,l0+1+q);
}
int matchstr(clsst *st,int p,int q,int x)
{
if(x<0) return 0;
if(q>k-x) return 1;
int step = match(st,p,q);
//cout<<"matchstr "<<p<<" "<<q<<" "<<x<<" "<<step<<endl;
p+=step-1;
q+=step-1;
if(q>=k-x) return 1;
else return matchstr(st,p+2,q+2,x-1);
}
int main(){
for(int i=1;i<=250000;i++) lg2[i]=log2(i);
scanf("%d",&T);
while(T--) {
memset(sa,0,sizeof sa);
memset(y,0,sizeof y);
memset(u,0,sizeof u);
memset(v,0,sizeof v);
memset(o,0,sizeof o);
memset(r,0,sizeof r);
memset(h,0,sizeof h);
memset(str,0,sizeof str);
scanf("%s",str+1);
n=l0=strlen(str+1);
str[n+1]='$';
scanf("%s",str+n+2);
k=strlen(str+n+2);
n+=k+1;
for(int i=1;i<=n;i++) u[str[i]]++;
for(int i=1;i<=m;i++) u[i]+=u[i-1];
for(int i=n;i>=1;i--) sa[u[str[i]]--]=i;
r[sa[1]]=1;
for(int i=2;i<=n;i++) r[sa[i]]=r[sa[i-1]]+(str[sa[i]]!=str[sa[i-1]]);
for(int l=1;r[sa[n]]<n;l<<=1) {
memset(u,0,sizeof u);
memset(v,0,sizeof v);
memcpy(o,r,sizeof r);
for(int i=1;i<=n;i++) u[r[i]]++, v[r[i+l]]++;
for(int i=1;i<=n;i++) u[i]+=u[i-1], v[i]+=v[i-1];
for(int i=n;i>=1;i--) y[v[r[i+l]]--]=i;
for(int i=n;i>=1;i--) sa[u[r[y[i]]]--]=y[i];
r[sa[1]]=1;
for(int i=2;i<=n;i++) r[sa[i]]=r[sa[i-1]]+((o[sa[i]]!=o[sa[i-1]])||(o[sa[i]+l]!=o[sa[i-1]+l]));
}
{
int i,j,k=0;
for(int i=1;i<=n;h[r[i++]]=k)
for(k?k--:0,j=sa[r[i]-1];str[i+k]==str[j+k];k++);
}
memset(st.a,0,sizeof st.a);
st.build(h,n);
int ans = 0;
for(int i=1;i<=l0-k+1;i++)
{
//cout<<"try "<<i<<endl;
int tmp = matchstr(&st,i,1,3);
//if(tmp==1) cout<<i<<endl;
ans += tmp;
}
cout<<ans<<endl;
}
}
[TJOI2017] DNA - 后缀数组,稀疏表的更多相关文章
- [TJOI2017]DNA --- 后缀数组
[TJOI2017]DNA 题目描述 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S, 有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其中不超过3个 ...
- [BZOJ4892][TJOI2017]DNA(后缀数组)
题目描述 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S,有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其中不超过3个碱基,依然能够表现出吃藕的性状 ...
- 洛谷P3763 [TJOI2017]DNA(后缀数组 RMQ)
题意 题目链接 Sol 这题打死我也不会想到后缀数组的,应该会全程想AC自动机之类的吧 但知道这题能用后缀数组做之后应该就不是那么难了 首先把\(S\)和\(S0\)拼到一起跑,求出Height数组 ...
- SPOJ 687 Repeats(后缀数组+ST表)
[题目链接] http://www.spoj.com/problems/REPEATS/en/ [题目大意] 求重复次数最多的连续重复子串的长度. [题解] 考虑错位匹配,设重复部分长度为l,记s[i ...
- POJ 3693 Maximum repetition substring(后缀数组+ST表)
[题目链接] poj.org/problem?id=3693 [题目大意] 求一个串重复次数最多的连续重复子串并输出,要求字典序最小. [题解] 考虑错位匹配,设重复部分长度为l,记s[i]和s[i+ ...
- BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay
BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔 ...
- UVA10829 L-Gap Substrings(后缀数组+ST表)
后缀数组+ST表. 代填的坑. \(Code\ Below:\) #include <bits/stdc++.h> #define ll long long using namespace ...
- POJ3693 Maximum repetition substring [后缀数组 ST表]
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9458 Acc ...
- 【BZOJ-4310】跳蚤 后缀数组 + ST表 + 二分
4310: 跳蚤 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 180 Solved: 83[Submit][Status][Discuss] De ...
随机推荐
- Enityt模型特性
数据验证相关的数据注解: 特性 解释 Remote 使用 jQuery 验证插件远程验证程序的特性 FileExtension 验证文件扩展名 Compare 比较两个属性的值 RegularExpr ...
- Mysql字符串截取,去掉时间,匹配日期等于今日
Mysql字符串截取,去掉时间,匹配日期等于今日 方案一 select time from jsb where date(time)=date(now()); 方案二 ));
- js内置对象的常用属性和方法(Array | String | Date | Math)
js内置对象:Array String Math Date <!DOCTYPE html> <html lang="en"> <head> ...
- Jenkins 插件安装问题
插件安装问题 尝试修改更新站点为可用的镜像站点 打开 Jenkins > Manage Jenkins > Manage Plugins > Advanced,将 Update Si ...
- openssl CVE-2016-2107 漏洞检测
最近在安装python3 时升级openssl 版本,在摸索openssl 升级过程中才发现centos6 默认安装的openssl 1.0.1e 版本是有一个严重的漏洞的(Padding oracl ...
- opencv —— imread、namedWindow & imshow、cvtColor、imwrite 加载、显示、修改、保存图像
加载图像:imread 函数 Mat imread(const string& filename, int flags = 1): filename:需要载入的图像的路径名. flags:加载 ...
- 【剑指Offer】58:二叉树的下一个结点
题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. 题解一:递归 //既然给了二叉树的某个结点,且二叉树存 ...
- Python的基本语法和数据类型(简明教程)
声明:借鉴Python 简明教程 一.注释 注释: 就是对代码的解释 方便大家阅读python代码,在编辑器中快捷键: notepad :ctrl + q pycharm: ctrl + / ...
- c# 使用T4模板生成实体类(sqlserver)
新建类库,右键添加 "文本模板" 添加完成之后生成如下后缀为 tt的文件: 双击文件:TextTemplate_Test.tt 文件打开,替换代码如下 <#@ templat ...
- Luogu2577 | [ZJOI2005]午餐 (贪心+DP)
题目描述 上午的训练结束了,THU ACM小组集体去吃午餐,他们一行 \(N\) 人来到了著名的十食堂.这里有两个打饭的窗口,每个窗口同一时刻只能给一个人打饭.由于每个人的口味(以及胃口)不同,所以他 ...