基因

给定一个长度为 \(n\) 的字符串 \(s\),有 \(q\) 组询问,每个询问给定 \(l,r\),询问 \(s[l..r]\) 中有多少本质不同的回文子串。

强制在线。\(n\leq 10^5,q ≤ 2n\)。

题解

翁文涛《回文树及其应用》。

“维护每个关键点到每个右端点的回文树”指的是维护 \((i,i\sim n)\) 的回文树。

往前端添加字符,\(fail\) 和 \(quick\) 都同后端一样。

回文树比较好的性质是加入一个之后节点数最多变化1,所以不用每次清空来处理答案。初始化的时候维护出了quick的话,以后就不用维护了,所以分块的复杂度少了一个 O(Σ)。

往前端加入字符的时候需要判断新增的节点是不是之前就出现过了的,这个可以对每个块维护每个节点第一次时间(未出现为 inf)。换种说法:为了去重,还需要记录一下Pam上每个节点在每个关键点为左端点插入到时候到最左边出现位置。

#include <bits/stdc++.h>
using namespace std; const int N = 101010;
const int M = 350; inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
template<typename T>
inline void read(T &x) {
static char c; x = 0; int sgn = 0;
for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
if (sgn) x = -x;
}
inline void read(char *s) {
static char c; int len = 0;
for (c = get(); c < 'a' || c > 'z'; c = get());
for (; c >= 'a' && c <= 'z'; c = get()) s[len++] = c;
s[len] = 0;
} char s[N];
int last_back, last_front, total;
int fail[N], len[N], ri[N];
int ch[N][30], quick[N][30];
int block_front[M][N], ans[M][N], block_time[M][N];
int visit[N];
int type, lastans, clocks;
int n, q, l, r, B;
int belong[N]; inline void ExtendFront(int pos, int r) {
int p = last_front, key = s[pos];
if (s[pos + len[p] + 1] != key || pos + len[p] + 1 > r) p = quick[p][key];
if (!ch[p][key]) {
int np = ++total, q = fail[p];
len[np] = len[p] + 2;
if (s[pos + len[q] + 1] == key) fail[np] = ch[q][key];
else fail[np] = ch[quick[q][key]][key];
memcpy(quick[np], quick[fail[np]], sizeof quick[np]);
quick[np][s[pos + len[fail[np]]]] = fail[np];
ch[p][key] = np;
}
last_front = ch[p][key];
if (len[last_front] == r - pos + 1) last_back = last_front;
}
inline void ExtendBack(int l, int pos) {
int p = last_back, key = s[pos];
if (s[pos - len[p] - 1] != key || pos - len[p] - 1 < l) p = quick[p][key];
if (!ch[p][key]) {
int np = ++total, q = fail[p];
len[np] = len[p] + 2;
if (s[pos - len[q] - 1] == key) fail[np] = ch[q][key];
else fail[np] = ch[quick[q][key]][key];
memcpy(quick[np], quick[fail[np]], sizeof quick[np]);
quick[np][s[pos - len[fail[np]]]] = fail[np];
ch[p][key] = np;
}
last_back = ch[p][key];
if (len[last_back] == pos - l + 1) last_front = last_back;
} int main(void) {
read(type); read(n); read(q);
read(s + 1); s[0] = -1;
for (int i = 1; i <= n; i++) s[i] -= 'a';
B = sqrt(n);
for (int i = 1; i <= n; i++) belong[i] = (i - 1) / B + 1; memset(block_time, 0x3f, sizeof block_time);
fail[0] = fail[1] = 1; len[1] = -1; total = 1;
for (int i = 0; i < 26; i++) quick[0][i] = quick[1][i] = 1; for (int i = 0; i < belong[n]; i++) {
++clocks; last_back = last_front = 0;
int st = i * B + 1;
for (int j = st; j <= n; j++) {
ExtendBack(st, j);
block_front[i][j] = last_front; ans[i][j] = ans[i][j - 1];
if (visit[last_back] != clocks) {
++ans[i][j]; visit[last_back] = clocks;
block_time[i][last_back] = j;
}
}
} while (q--) {
read(l); read(r); ++clocks;
l ^= type * lastans;
r ^= type * lastans;
if (l > r) swap(l, r);
if (belong[l] == belong[r]) {
last_back = last_front = 0; lastans = 0;
for (int i = r; i >= l; i--) {
ExtendFront(i, r);
if (visit[last_front] != clocks) {
++lastans; visit[last_front] = clocks;
}
}
} else {
lastans = ans[belong[l]][r];
last_front = block_front[belong[l]][r];
for (int i = belong[l] * B; i >= l; i--) {
ExtendFront(i, r);
if (visit[last_front] != clocks) {
visit[last_front] = clocks;
if (block_time[belong[l]][last_front] > r) ++lastans;
}
}
}
printf("%d\n", lastans);
}
return 0;
}

LOJ6070 基因的更多相关文章

  1. LOJ6070 基因 分块+回文自动机

    这个在翁文涛的论文里有讲到 大概的就是一个子串的回文自动机是原串回文自动机的子图 于是每隔$\sqrt n$重新跑一个$(k \times \sqrt n,n)$的回文自动机 记录回文串个数和位置 并 ...

  2. 使用limma、Glimma和edgeR,RNA-seq数据分析易如反掌

    使用limma.Glimma和edgeR,RNA-seq数据分析易如反掌 Charity Law1, Monther Alhamdoosh2, Shian Su3, Xueyi Dong3, Luyi ...

  3. loj6070【山东集训第一轮Day4】基因

    题解: 分块对每个块的起点$st[i]$到$n$做一次回文自动机; 由于子串的回文自动机是原串的子图,所以并不需要重新构图,在原来的图上做即可: 做的时候记录某个终点的本质不同的回文串和$sum[i] ...

  4. 基因匹配(bzoj 1264)

    Description 基因匹配(match) 卡卡昨天晚上做梦梦见他和可可来到了另外一个星球,这个星球上生物的DNA序列由无数种碱基排列而成(地球上只有4种),而更奇怪的是,组成DNA序列的每一种碱 ...

  5. 1264: [AHOI2006]基因匹配Match

    1264: [AHOI2006]基因匹配Match Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 982  Solved: 635[Submit][S ...

  6. 【GWAS文献】基于GWAS与群体进化分析挖掘大豆相关基因

    Resequencing 302 wild and cultivated accessions identifies genes related to domestication and improv ...

  7. AC日记——基因相关性 openjudge 1.7 03

    03:基因相关性 总时间限制:  1000ms 内存限制:   65536kB 描述 为了获知基因序列在功能和结构上的相似性,经常需要将几条不同序列的DNA进行比对,以判断该比对的DNA是否具有相关性 ...

  8. luogu[1140]相似基因

    题目背景 大家都知道,基因可以看作一个碱基对序列.它包含了4种核苷酸,简记作A,C,G,T.生物学家正致力于寻找人类基因的功能,以利用于诊断疾病和发明药物. 在一个人类基因工作组的任务中,生物学家研究 ...

  9. 用excel绘制基因芯片热力图

    1.  首先我们通过一些方法得到了如下的数据,基于篇幅以及为了教学隐去了其他一些信息. 2. 选中表达数据,执行 开始—条件格式—色阶 选择一个合适的色阶: 3. 选择好颜色之后得到了如下结果:

随机推荐

  1. ACM | 算法 | 快速幂

    目录 快速幂 快速幂取模 矩阵快速幂 矩阵快速幂取模 HDU1005练习 快速幂 ​ 幂运算:\(x ^ n\) ​ 根据其一般定义我们可以简单实现其非负整数情况下的函数 定义法: int Pow ( ...

  2. SpringBoot:4.SpringBoot整合Mybatis实现数据库访问

    在公司项目开发中,使用Mybatis居多.在 SpringBoot:3.SpringBoot使用Spring-data-jpa实现数据库访问 中,这种jpa风格的把sql语句和java代码放到一起,总 ...

  3. Centos 使用kubeadm安装Kubernetes 1.15.3

    本来没打算搞这个文章的,第一里面有瑕疵(没搞定的地方),第二在我的Ubuntu 18 Kubernetes集群的安装和部署 以及Helm的安装 也有安装,第三 和社区的问文章比较雷同 https:// ...

  4. RabbitMQ学习之Publish/Subscribe(3)

    上一个教程中,我们创建了一个work queue. 其中的每个task都会被精确的传送到一个worker. 这节,我们将会讲把一个message传送到多个consumers. 这种模式叫做publis ...

  5. Kubeadm 1.9 HA 高可用集群本地离线镜像部署【已验证】

    k8s介绍 k8s 发展速度很快,目前很多大的公司容器集群都基于该项目,如京东,腾讯,滴滴,瓜子二手车,易宝支付,北森等等. kubernetes1.9版本发布2017年12月15日,每三个月一个迭代 ...

  6. 使用HttpClient访问接口(Rest接口和普通接口)

    这里总结一下使用HttpClient访问外部接口的用法.后期如果发现有什么缺陷会更改.欢迎读者指出此方法的不足之处. 首先,创建一个返回实体: public class HttpResult { // ...

  7. C#实现电信短信SMGP协议程序源码

    此程序为中国电信SMGP协议程序接口,适合在中国电信申请了短信发送端口的公司使用. 短信群发已经成为现在软件系统.网络营销等必不可少的应用工具.可应用在短信验证.信息群发.游戏虚拟商品购买.事件提醒. ...

  8. 简单了解Eureka

    1.Eureka简介 Eureka是Spring Cloud Netflix微服务套件中的一部分,是一套成熟的服务注册和发现组件,可以与Springboot构建的微服务很容易的整合起来. Eureka ...

  9. 全程实操cdh5.14.4中集成安装kylin2.4.1与使用测试

    在cdh5.14.4安装完成并排错完成的情况下,进行如下kylin安装操作: 1.实验环境 三台CentOS 7主机,IP地址 192.168.43.129 cm1 192.168.43.130 cm ...

  10. 2年java,蚂蚁一面,卒

    其实我一个都没答上来.并不是因为我笨,是因为我不会.在大扰的帮助下,现在我会了,求求你再给我一个机会. TreeSet/HashSet 区别 顾名思义,首先是结构上的不同 1.TreeSet背后的结构 ...