洛谷P3763 [TJOI2017]DNA(后缀数组 RMQ)
题意
Sol
这题打死我也不会想到后缀数组的,应该会全程想AC自动机之类的吧
但知道这题能用后缀数组做之后应该就不是那么难了
首先把\(S\)和\(S0\)拼到一起跑,求出Height数组
暴力枚举每个后缀是否能成为答案。
具体来说,每次比较当前后缀和\(S_0\)的lcp,如果长度\(< N\)的话就从不合法的位置继续匹配
rmq维护一下区间lcp最小值
BZOJ上被完美卡常
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 10;
const int INF = 2333;
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int N, M, L, rak[MAXN], tax[MAXN], tp[MAXN], sa[MAXN], H[MAXN], f[MAXN][20], lg2[MAXN];
char s[MAXN], s0[MAXN];
void Qsort() {
for(int i = 0; i <= M; i++) tax[i] = 0;
for(int i = 1; i <= N; i++) tax[rak[i]]++;
for(int i = 1; i <= M; i++) tax[i] += tax[i - 1];
for(int i = N; i >= 1; i--) sa[tax[rak[tp[i]]]--] = tp[i];
}
void SuffixSort() {
for(int i = 1; i <= N; i++) rak[i] = s[i], tp[i] = i; M = 233; Qsort();
for(int w = 1, p = 0; p < N; w <<= 1, M = p) { p = 0;
for(int i = 1; i <= w; i++) tp[++p] = N - i + 1;
for(int i = 1; i <= N; i++) if(sa[i] > w) tp[++p] = sa[i] - w;
Qsort(); swap(tp, rak); rak[sa[1]] = p = 1;
for(int i = 2; i <= N; i++) rak[sa[i]] = (tp[sa[i]] == tp[sa[i - 1]] && tp[sa[i] + w] == tp[sa[i - 1] + w]) ? p : ++p;
}
for(int i = 1, k = 0; i <= N; i++) {
if(k) k--; int j = sa[rak[i] - 1];
while(s[i + k] == s[j + k]) k++;
H[rak[i]] = k;
}
}
void Pre() {
for(int i = 1; i <= N; i++) f[i][0] = H[i];
for(int j = 1; j <= 17; j++)
for(int i = 1; i + (1 << j) - 1 <= N; i++) f[i][j] = min(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
}
int Query(int x, int y) {
if(x > y) swap(x, y); x++;
int k = lg2[y - x + 1];
return min(f[x][k], f[y - (1 << k) + 1][k]);
}
int check(int x, int y, int dep) {
if(dep == 3) return Query(rak[x], rak[y]);
int num = Query(rak[x], rak[y]);
num += check(x + num + 1, y + num + 1, dep + 1) + 1;
return num;
}
void solve() {
scanf("%s%s", s + 1, s0 + 1);
L = strlen(s0 + 1); N = strlen(s + 1);
for(int i = 1; i <= L; i++) s[N + i] = s0[i];
N += L;
SuffixSort(); Pre(); N -= L; int ans = 0;
for(int i = 1; i <= N - L + 1; i++) if(check(i, N + 1, 0) >= L) ans++;
printf("%d\n", ans);
}
int main() {
//freopen("a.in", "r", stdin);
lg2[1] = 0; for(int i = 2; i <= MAXN - 1; i++) lg2[i] = lg2[i >> 1] + 1;
for(int T = read(); T; solve(), T--);
return 0;
}
/*
2
ATCGCCCTA
CTTCA
ATCGCCCTA
CTTCA
*/
洛谷P3763 [TJOI2017]DNA(后缀数组 RMQ)的更多相关文章
- 洛谷P3763 [Tjoi2017]DNA 【后缀数组】
题目链接 洛谷P3763 题解 后缀数组裸题 在BZOJ被卡常到哭QAQ #include<algorithm> #include<iostream> #include< ...
- [洛谷P3763] [TJOI2017]DNA
洛谷题目链接:[TJOI2017]DNA 题目描述 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S,有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其 ...
- 洛谷P3763 [TJOI2017]DNA(后缀自动机)
传送门 好像用SAM写的很少诶…… 其实我一开始也没想到要用SAM的……主要是没有想到找的时候可以dfs…… 首先建一个SAM,然后跑一遍dfs,枚举一下下一位,如果相同直接继续,否则就花费一次次数来 ...
- [TJOI2017] DNA - 后缀数组,稀疏表
[TJOI2017] DNA Description 求模式串与主串的匹配次数,容错不超过三个字符. Solution 枚举每个开始位置,进行暴力匹配,直到失配次数用光或者匹配成功.考虑到容错量很小, ...
- [TJOI2017]DNA --- 后缀数组
[TJOI2017]DNA 题目描述 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S, 有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其中不超过3个 ...
- [BZOJ4892][TJOI2017]DNA(后缀数组)
题目描述 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S,有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其中不超过3个碱基,依然能够表现出吃藕的性状 ...
- 洛谷-P3809-后缀排序(后缀数组)
看了求后缀数组的倍增法之后很快就理解了,但是自己写的倍增法用map排序还是超时了.然后看了两天别人写的模板,题目是通过了,但感觉代码还是半懂半背的.以后多熟悉熟悉吧: 后缀数组 #include &q ...
- 洛谷 P4143 采集矿石 后缀数组
题目背景 ZRQ 成功从坍塌的洞穴中逃了出来.终于,他看到了要研究的矿石.他想挑一些带回去完成任务. 题目来源:Zhang_RQ哦对了 \(ZRQ\) 就他,嗯 题目描述 ZRQ 发现这里有 \(N\ ...
- 洛谷3809 SA模板 后缀数组学习笔记(复习)
其实SA这个东西很久之前就听过qwq 但是基本已经忘的差不多了 嘤嘤嘤 QWQ感觉自己不是很理解啊 所以写不出来那种博客 QWQ只能安利一些别人的博客了 小老板 真的是讲的非常好 不要在意名字 orz ...
随机推荐
- java的应用,SVN客户端的安装教程
1.先注册一个百度云账号,然后打开https://console.bce.baidu.com 这个网站,按照下面的图形点击 !!!!请注意这是要收钱的,但能学习到那用微信打开你的网站也是值得的. 2. ...
- 39.oracle高级篇
标题说是高级篇,其实也就是相对于基础篇来说的,也不是很深奥,自己平时工作中也都会用到,这里回忆的并不是特别冷门的知识,不要掉以轻心,以为“高级”就觉得工作中不会用到了. 一.select into 和 ...
- JS设计模式之单体模式(Singleton)
单体模式作为一种软件开发模式在众多面向对象语言中得到了广泛的使用,在javascript中,单体模式也是使用非常广泛的,但是由于javascript语言拥有其独特的面向对象方式,导致其和一些传统面向对 ...
- string容器的简单实现
1.业务使用main.cpp #include "pch.h" #include <iostream> int main() { mystring s1;//无参构造函 ...
- rdlc报表函数
字符串函数 使用串联运算符和 Visual Basic 常量可将多个字段组合在一起.以下表达式返回两个字段,它们分别位于同一文本框的不同行中: 复制代码 =Fields!FirstName. ...
- tomcat startup.brt启动一闪而过
今天启动皕杰自带的tomcat的时候,直接点startup.brt控制台窗口一闪而过. 改用cmd命令启动: 切换到 E:\皕杰报表\皕杰报表3.5\DemoServer\bin目录 运行startu ...
- Mac 10.12安装粘贴板增加工具ClipMenu
说明:这个工具可以保留复制过的记录,并且可以快速调出之前复制过的内容,最开发时比较常用,支持图片等. 下载: (链接: https://pan.baidu.com/s/1qXJbM2o 密码: wef ...
- html网页如何传递接收地址参数?
实现html页面的参数传递 方法一: 下面是javascrīpt的一种实现方法, 这个函数是通过window.location.href中的分割符获得各个参数. 有了这个函数,就可以在页面之间传递参数 ...
- Hadoop Gateway 部署
1.集群的 hadoop-current hive-current spark-current copy 到 gateway 机器 2.集群的 hadoop-conf hive-conf ...
- ruby gems列表
https://github.com/shageman/cobradeps