洛谷P3763 [Tjoi2017]DNA 【后缀数组】
题目链接
题解
后缀数组裸题
在BZOJ被卡常到哭QAQ
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (register int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
#define res register
using namespace std;
const int maxn = 200005,maxm = 100005,INF = 1000000000;
inline int read(){
res int out = 0,flag = 1; res char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
char s[maxn],s2[maxn];
int sa[maxn],rank[maxn],height[maxn],bac[maxn],t1[maxn],t2[maxn],mn[maxn][18],n,m;
int bin[50],Log[maxn],lenp,lent;
inline void getsa(){
int *x = t1,*y = t2; m = 255;
for (res int i = 0; i <= m; i++) bac[i] = 0;
for (res int i = 1; i <= n; i++) bac[x[i] = s[i]]++;
for (res int i = 1; i <= m; i++) bac[i] += bac[i - 1];
for (res int i = n; i; i--) sa[bac[x[i]]--] = i;
for (res int k = 1; k <= n; k <<= 1){
int p = 0;
for (res int i = n - k + 1; i <= n; i++) y[++p] = i;
for (res int i = 1; i <= n; i++) if (sa[i] - k > 0) y[++p] = sa[i] - k;
for (res int i = 0; i <= m; i++) bac[i] = 0;
for (res int i = 1; i <= n; i++) bac[x[y[i]]]++;
for (res int i = 1; i <= m; i++) bac[i] += bac[i - 1];
for (res int i = n; i; i--) sa[bac[x[y[i]]]--] = y[i];
swap(x,y);
x[sa[1]] = p = 1;
for (res int i = 2; i <= n; i++)
x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k] ? p : ++p);
if (p >= n) break;
m = p;
}
for (res int i = 1; i <= n; i++) rank[sa[i]] = i;
for (res int i = 1,k = 0; i <= n; i++){
if (k) k--;
int j = sa[rank[i] - 1];
while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) k++;
height[rank[i]] = k;
}
for (res int i = 1; i <= n; i++) mn[i][0] = height[i];
REP(j,17) REP(i,n){
if (i + bin[j] - 1 > n) break;
mn[i][j] = min(mn[i][j - 1],mn[i + bin[j - 1]][j - 1]);
}
}
inline int lcp(int x,int y){
int l = rank[x],r = rank[y];
if (l > r) swap(l,r); l++;
int t = Log[r - l + 1];
return min(mn[l][t],mn[r - bin[t] + 1][t]);
}
void solve(){
int ans = 0;
for (res int i = 1; i <= lenp - lent + 1; i++){
res int j = 1,tmp,cnt = 3;
while (cnt && j <= lent){
tmp = lcp(i + j - 1,lenp + 1 + j);
if (!tmp) j++,cnt--;
else j += tmp;
}
if (j <= lent){
j += lcp(i + j - 1,lenp + 1 + j);
}
if (j > lent){
ans++;
}
}
printf("%d\n",ans);
}
int main(){
bin[0] = 1; REP(i,25) bin[i] = bin[i - 1] << 1;
Log[0] = -1; REP(i,200000) Log[i] = Log[i >> 1] + 1;
int T = read();
while (T--){
scanf("%s",s + 1); lenp = strlen(s + 1);
s[lenp + 1] = 1; s[lenp + 2] = '\0';
scanf("%s",s2 + 1); lent = strlen(s2 + 1);
strcat(s + 1,s2 + 1);
n = lenp + 1 + lent;
getsa();
solve();
}
return 0;
}
洛谷P3763 [Tjoi2017]DNA 【后缀数组】的更多相关文章
- 洛谷P3763 [TJOI2017]DNA(后缀数组 RMQ)
题意 题目链接 Sol 这题打死我也不会想到后缀数组的,应该会全程想AC自动机之类的吧 但知道这题能用后缀数组做之后应该就不是那么难了 首先把\(S\)和\(S0\)拼到一起跑,求出Height数组 ...
- [洛谷P3763] [TJOI2017]DNA
洛谷题目链接:[TJOI2017]DNA 题目描述 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S,有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其 ...
- 洛谷P3763 [TJOI2017]DNA(后缀自动机)
传送门 好像用SAM写的很少诶…… 其实我一开始也没想到要用SAM的……主要是没有想到找的时候可以dfs…… 首先建一个SAM,然后跑一遍dfs,枚举一下下一位,如果相同直接继续,否则就花费一次次数来 ...
- [TJOI2017]DNA --- 后缀数组
[TJOI2017]DNA 题目描述 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S, 有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其中不超过3个 ...
- [TJOI2017] DNA - 后缀数组,稀疏表
[TJOI2017] DNA Description 求模式串与主串的匹配次数,容错不超过三个字符. Solution 枚举每个开始位置,进行暴力匹配,直到失配次数用光或者匹配成功.考虑到容错量很小, ...
- [BZOJ4892][TJOI2017]DNA(后缀数组)
题目描述 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S,有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其中不超过3个碱基,依然能够表现出吃藕的性状 ...
- 洛谷-P3809-后缀排序(后缀数组)
看了求后缀数组的倍增法之后很快就理解了,但是自己写的倍增法用map排序还是超时了.然后看了两天别人写的模板,题目是通过了,但感觉代码还是半懂半背的.以后多熟悉熟悉吧: 后缀数组 #include &q ...
- 洛谷 P4143 采集矿石 后缀数组
题目背景 ZRQ 成功从坍塌的洞穴中逃了出来.终于,他看到了要研究的矿石.他想挑一些带回去完成任务. 题目来源:Zhang_RQ哦对了 \(ZRQ\) 就他,嗯 题目描述 ZRQ 发现这里有 \(N\ ...
- 洛谷3809 SA模板 后缀数组学习笔记(复习)
其实SA这个东西很久之前就听过qwq 但是基本已经忘的差不多了 嘤嘤嘤 QWQ感觉自己不是很理解啊 所以写不出来那种博客 QWQ只能安利一些别人的博客了 小老板 真的是讲的非常好 不要在意名字 orz ...
随机推荐
- ThinkPHP框架目录的介绍
library目录 Think目录 mvc
- ZooKeeper(2)-安装和配置
一.下载 https://zookeeper.apache.org/ 二.本地模式安装 1.安装前准备 (1)安装Jdk (2)拷贝Zookeeper安装包到Linux系统下 (3)解压到指定目录 . ...
- hive-show-partitions
展示分区命令 show partitions show partitions 可以展示这个表格之下的所有分区信息.这个命令常常用在使用SQL语句操作数据之前.举个简单的例子,如果我们想要根据uid融合 ...
- Leecode刷题之旅-C语言/python-118杨辉三角
/* * @lc app=leetcode.cn id=118 lang=c * * [118] 杨辉三角 * * https://leetcode-cn.com/problems/pascals-t ...
- count_char
import java.util.Scanner; public class count_char { public static void main(String args[]) { int cou ...
- (数据科学学习手札12)K-means聚类实战(基于R)
上一篇我们详细介绍了普通的K-means聚类法在Python和R中各自的实现方法,本篇便以实际工作中遇到的数据集为例进行实战说明. 数据说明: 本次实战样本数据集来自浪潮集团提供的美团的商家信息,因涉 ...
- 面试官常问的10个Linux问题
1.如何暂停一个正在运行的进程,把其放在后台(不运行)? 为了停止正在运行的进程,让其再后台运行,我们可以使用组合键Ctrl+Z. 2.什么是安装Linux所需的最小分区数量,以及如何查看系统启动信息 ...
- spring boot 入门3 如何在springboot 上使用AOP
Aop是spring的两大核心之一 那么如何在springboot中采用注解的形式实现aop那? 1)首先我们定义一个相关功能的切面类 并 采用@Aspect 注解来声明当前类为切面 同时采用@Com ...
- Linux上jdk的安装(CentOS6.5)
centos openjdk 安装 http://www.cnblogs.com/ilahsa/archive/2012/12/11/2813059.html 知CentOS6.5桌面版默认安装的是J ...
- ASP.NET MVC 使用jquery.form.js 异步上传 在IE下返回值被变为下载的解决办法
错误记录: <script type="text/javascript"> $(function () { $(document).off("ajaxSend ...