BZOJ2555. SubString

要求在线询问一个串在原串中出现的次数,并且可以在原串末尾添加字符串

如果没有修改的话,考虑建出\(parent\)树之后统计每个\(endpos\)节点的\(right\)集合大小,现在要求动态添加字符,那么由于\(parent\)树的形态会变,所以用\(LCT\)来维护\(parent\)树,具体就是增删\(link\)边

\(LCT\)一直以初始状态为根,每次提出来初始状态到当前节点的链然后更新一条链上的值即可,根一直没变,不需要\(makeroot\)操作也不需要\(split\)操作,直接\(access\)当前点,然后\(splay\)上去之后更新

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
const int MAXN = (6e5+7)*2;
void decode(string& str, int mask){
for(int i = 0; i < (int)str.size(); i++){
mask = (mask*131+i)%str.size();
swap(str[i],str[mask]);
}
}
struct LinkCutTree{
int ch[MAXN][2],fa[MAXN],val[MAXN],lazy[MAXN],rev[MAXN];
bool isroot(int rt){ return ch[fa[rt]][0]!=rt and ch[fa[rt]][1]!=rt; }
int check(int rt){ return rt == ch[fa[rt]][1]; }
void pushdown(int rt){
if(rev[rt]){
swap(ch[rt][0],ch[rt][1]);
rev[ch[rt][0]] ^= 1;
rev[ch[rt][1]] ^= 1;
rev[rt] ^= 1;
}
if(lazy[rt]){
if(ch[rt][0]){
val[ch[rt][0]] += lazy[rt];
lazy[ch[rt][0]] += lazy[rt];
}
if(ch[rt][1]){
val[ch[rt][1]] += lazy[rt];
lazy[ch[rt][1]] += lazy[rt];
}
lazy[rt] = 0;
}
}
void pushdownall(int rt){
if(!isroot(rt)) pushdownall(fa[rt]);
pushdown(rt);
}
void rotate(int rt){
int f = fa[rt], gf = fa[f], d = check(rt);
if(!isroot(f)) ch[gf][check(f)] = rt;
fa[rt] = gf;
ch[f][d] = ch[rt][d^1]; fa[ch[rt][d^1]] = f;
ch[rt][d^1] = f; fa[f] = rt;
}
void splay(int rt){
pushdownall(rt);
while(!isroot(rt)){
int f = fa[rt];
if(!isroot(f)){
if(check(rt)==check(f)) rotate(f);
else rotate(rt);
}
rotate(rt);
}
}
void access(int rt){
int c = 0;
while(rt){
splay(rt);
ch[rt][1] = c;
rt = fa[c = rt];
}
}
void link(int x, int f){
fa[x] = f; access(f); splay(f);
val[f] += val[x]; lazy[f] += val[x];
}
void cut(int u){
access(u);
splay(u);
lazy[ch[u][0]] -= val[u];
val[ch[u][0]] -= val[u];
fa[ch[u][0]] = 0; ch[u][0] = 0;
}
int query(int u){
splay(u);
return val[u];
}
}lct;
struct SAM{
int len[MAXN],link[MAXN],ch[MAXN][26],tot,last;
SAM(){ link[last = tot = 1] = 0; }
void extend(int c){
int np = ++tot, p = last;
lct.val[np] = 1;
len[np] = len[last] + 1;
while(p and !ch[p][c]){
ch[p][c] = np;
p = link[p];
}
if(!p){
link[np] = 1;
lct.link(np,1);
}
else{
int q = ch[p][c];
if(len[p]+1==len[q]){
link[np] = q;
lct.link(np,q);
}
else{
int clone = ++tot;
len[clone] = len[p] + 1;
link[clone] = link[q];
lct.link(clone,link[q]);
for(int i = 0; i < 26; i++) ch[clone][i] = ch[q][i];
lct.cut(q); lct.link(q,clone);
lct.link(np,clone);
link[np] = link[q] = clone;
while(p and ch[p][c]==q){
ch[p][c] = clone;
p = link[p];
}
}
}
last = np;
}
int calsub(string s){
int u = 1;
for(int i = 0; i < (int)s.size(); i++){
int c = s[i] - 'A';
if(!ch[u][c]) return 0;
u = ch[u][c];
}
return lct.query(u);
}
}sam;
int n,mask;
string s,op;
int main(){
//ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n >> s;
for(int i = 0; i < (int)s.size(); i++) sam.extend(s[i]-'A');
while(n--){
cin >> op >> s;
decode(s,mask);
if(op[0]=='Q'){
int ret = sam.calsub(s);
mask ^= ret;
cout << ret << endl;
}
else for(int i = 0; i < (int)s.size(); i++) sam.extend(s[i]-'A');
}
return 0;
}

BZOJ2555 SubString【SAM + Link Cut Tree】的更多相关文章

  1. [BZOJ 1036] [ZJOI2008] 树的统计Count 【Link Cut Tree】

    题目链接:BZOJ - 1036 题目分析 这道题可以用树链剖分,块状树等多种方法解决,也可以使用 LCT. 修改某个点的值时,先将它 Splay 到它所在的 Splay 的根,然后修改它的值,再将它 ...

  2. CF614A 【Link/Cut Tree】

    题意:求出所有w^i使得l<=w^i<=r 输入为一行,有三个数,分别是l,r,w.意义如题目所描述 输出为一行,输出所有满足条件的数字,每两个数字中间有一个空格 如果没有满足条件的数字则 ...

  3. P3690 【模板】Link Cut Tree (动态树)

    P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...

  4. LG3690 【模板】Link Cut Tree (动态树)

    题意 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的 ...

  5. AC日记——【模板】Link Cut Tree 洛谷 P3690

    [模板]Link Cut Tree 思路: LCT模板: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 30 ...

  6. LG3690 【模板】Link Cut Tree 和 SDOI2008 洞穴勘测

    UPD:更新了写法. [模板]Link Cut Tree 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 后接两个整数(x,y),代表询问从x到y ...

  7. (RE) luogu P3690 【模板】Link Cut Tree

    二次联通门 : luogu P3690 [模板]Link Cut Tree 莫名RE第8个点....如果有dalao帮忙查错的话万分感激 #include <cstdio> #includ ...

  8. LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板

    P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...

  9. 【刷题】洛谷 P3690 【模板】Link Cut Tree (动态树)

    题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...

随机推荐

  1. Serverless 如何应对 K8s 在离线场景下的资源供给诉求

    本文整理自腾讯云云原生产品团队的专家产品经理韩沛在 Techo 开发者大会云原生专题的分享内容--Kubernetes 混部与弹性容器.本次分享主要分为三部分:基于 K8s 的应用混部.提升应用混部效 ...

  2. 浅谈JVM垃圾回收

    JVM内存区域 要想搞懂啊垃圾回收机制,首先就要知道垃圾回收主要回收的是哪些数据,这些数据主要在哪一块区域. Java8和Java8之前的相同点有很多. 都有虚拟机栈,本地方法栈,程序计数器,这三个是 ...

  3. 【Linux】ethtool 用法

    ethtool命令用于获取以太网卡的配置信息,或者修改这些配置.这个命令比较复杂,功能特别多. 语法 ethtool [ -a | -c | -g | -i | -d | -k | -r | -S | ...

  4. 电子邮箱、邮件地址、网站地址正则表达式!几个有用的RE、regex、regexp!

    几个常用的正则表达式! r"\w[-\w\.]*@\w[-\w]*(\.\w[-\w]*)+" 这个是电子邮件地址的. r"<TAG\b[^>]*<(. ...

  5. ctfhub技能树—信息泄露—git泄露—Log

    什么是git泄露? 当前大量开发人员使用git进行版本控制,对站点自动部署.如果配置不当,可能会将.git文件夹直接部署到线上环境.这就引起了git泄露漏洞. 打开靶机环境 查看网页内容 使用dirs ...

  6. three.js cannon.js物理引擎之约束

    今天郭先生继续说cannon.js,主演内容就是点对点约束和2D坐标转3D坐标.仍然以一个案例为例,场景由一个地面.若干网格组成的约束体和一些拥有初速度的球体组成,如下图.线案例请点击博客原文. 下面 ...

  7. 词嵌入之Word2Vec

    词嵌入要解决什么问题 在自然语言系统中,词被看作最为基本的单元,如何将词进行向量化表示是一个很基本的问题,词嵌入(word embedding)就是把词映射为低维实数域向量的技术. 下面先介绍几种词的 ...

  8. [Usaco2007 Dec]宝石手镯

    题目描述 贝茜在珠宝店闲逛时,买到了一个中意的手镯.很自然地,她想从她收集的 N(1 <= N <= 3,402)块宝石中选出最好的那些镶在手镯上.对于第i块宝石,它的重量为W_i(1 & ...

  9. UI测试框架

    1. 从上到下共分成4层: 用例层  组件管理层  元素管理层  公共数据层 2. 用例层: 将每条用例使用参数化, 公共参数存储到"公共数据层", 中间参数通过组件层传递 3. ...

  10. ROS教程(一):ROS安装教程(详细图文)

    ros教程:ros安装 目录 前言 一.版本选择 二.开始安装 2.1 软件中心配置 2.2 添加源 2.3 安装 三.验证ROS 前言 关于ROS(Robot OS 机器人操作系统),估计看这个教程 ...