【BZOJ2555】SubString(后缀自动机,LCT)
题意:给你一个字符串init,要求你支持两个操作
(1):在当前字符串的后面插入一个字符串
(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
你必须在线支持这些操作。
长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000
思路:因为有加边,删边,加点操作,需要动态维护SAM中每个right集合的大小,所以使用LCT维护
需要维护根节点=1号点到每个结点路径上的和,因为固定了1号点为根节点所以不需要makeroot和rev标记
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> Pll;
typedef vector<int> VI;
typedef vector<PII> VII;
typedef pair<ll,int>P;
#define N 1200010
#define M 210000
#define fi first
#define se second
#define MP make_pair
#define pi acos(-1)
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
#define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
#define lowbit(x) x&(-x)
#define Rand (rand()*(1<<16)+rand())
#define id(x) ((x)<=B?(x):m-n/(x)+1)
#define ls p<<1
#define rs p<<1|1 const int MOD=1e9+,inv2=(MOD+)/;
double eps=1e-;
int INF=<<;
ll inf=5e13;
int dx[]={-,,,};
int dy[]={,,-,}; int mask;
char s[];
string chars; int read()
{
int v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} void gets(int mask)
{
scanf("%s",s);
chars=s;
for(int j=;j<chars.length();j++)
{
mask=(mask*+j)%chars.length();
char t=chars[j];
chars[j]=chars[mask];
chars[mask]=t;
}
} struct lct
{
int t[N][],w[N],fa[N],q[N],rev[N],tag[N],top; void add(int x,int y)
{
if(x)
{
w[x]+=y;
tag[x]+=y;
}
} int isroot(int x)
{
return ((t[fa[x]][]!=x)&&(t[fa[x]][]!=x));
} void pushdown(int x)
{
int l=t[x][],r=t[x][];
if(tag[x])
{
add(l,tag[x]);
add(r,tag[x]);
tag[x]=;
}
} void rotate(int x)
{
int y=fa[x],z=fa[y];
int l=(t[y][]==x),r=l^;
if(!isroot(y)) t[z][t[z][]==y]=x;
fa[t[x][r]]=y,fa[y]=x,fa[x]=z;
t[y][l]=t[x][r],t[x][r]=y;
} void splay(int x)
{
top=;
q[++top]=x;
for(int i=x;!isroot(i);i=fa[i]) q[++top]=fa[i];
while(top) pushdown(q[top--]);
while(!isroot(x))
{
int y=fa[x],z=fa[y];
if(!isroot(y))
{
if((t[y][]==x)^(t[z][]==y)) rotate(x);
else rotate(y);
}
rotate(x);
}
} void access(int x)
{
for(int k=;x;k=x,x=fa[x])
{
splay(x);
t[x][]=k;
}
} void link(int x,int y)
{
fa[x]=y;
access(y);
splay(y);
add(y,w[x]);
} void cut(int x)
{
access(x);
splay(x);
add(t[x][],-w[x]);
fa[t[x][]]=;
t[x][]=;
} }lct; struct sam
{
int cnt;
int F[N],ch[N][];
int st[N],b[N],bl[N],c[N];
int p,np,q,nq; sam()
{
cnt=np=;
} void extend(int x)
{
p=np; st[np=++cnt]=st[p]+;
while(p&&!ch[p][x])
{
ch[p][x]=np;
p=F[p];
}
lct.w[np]=;
if(!p) F[np]=,lct.link(np,);
else if(st[p]+==st[q=ch[p][x]]) F[np]=q,lct.link(np,q);
else
{
st[nq=++cnt]=st[p]+;
memcpy(ch[nq],ch[q],sizeof ch[q]);
F[nq]=F[q];
lct.link(nq,F[q]);
F[np]=F[q]=nq;
lct.cut(q);
lct.link(q,nq);
lct.link(np,nq);
while(ch[p][x]==q)
{
ch[p][x]=nq;
p=F[p];
}
}
} void build()
{
scanf("%s",s);
int n=strlen(s);
rep(i,,n-) extend(s[i]-'A');
} void add()
{
gets(mask);
int n=chars.length();
rep(i,,n-) extend(chars[i]-'A');
} int query()
{
gets(mask);
int p=,n=chars.length();
rep(i,,n-)
{
p=ch[p][chars[i]-'A'];
if(!p) return ;
}
lct.splay(p);
return lct.w[p];
} }sam; int main()
{
int Q;
scanf("%d",&Q);
sam.build();
while(Q--)
{
scanf("%s",s);
if(s[]=='A') sam.add();
else
{
int ans=sam.query();
printf("%d\n",ans);
mask^=ans;
}
}
return ;
}
【BZOJ2555】SubString(后缀自动机,LCT)的更多相关文章
- luogu5212/bzoj2555 substring(后缀自动机+动态树)
对字符串构建一个后缀自动机. 每次查询的就是在转移边上得到节点的parent树中后缀节点数量. 由于强制在线,可以用动态树维护后缀自动机parent树的子树和. 注意一个玄学的优化:每次在执行连边操作 ...
- bzoj 2555 SubString —— 后缀自动机+LCT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555 建立后缀自动机,就可以直接加入新串了: 出现次数就是 Right 集合的大小,需要查询 ...
- 【BZOJ2555】SubString 后缀自动机+LCT
[BZOJ2555]SubString Description 懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2 ...
- bzoj 2555: SubString 后缀自动机+LCT
2555: SubString Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 688 Solved: 235[Submit][Status][Dis ...
- bzoj 2555 SubString——后缀自动机+LCT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555 要维护 right 集合的大小.因为 fa 会变,且 fa 构成一棵树,所以考虑用 L ...
- BZOJ2555 SubString 【后缀自动机 + LCT】
题目 懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支持这些操作. 输入 ...
- bzoj2555(后缀自动机+LCT)
题目描述 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支持这些操作. 题解 做法很自然,建出后缀自动机,维护每个节点的right ...
- bzoj 2555: SubString【后缀自动机+LCT】
一直WA--找了半天错的发现居然是解密那里的mask其实是不能动的--传进去的会变,但是真实的那个不会变-- 然后就是后缀自动机,用LCT维护parent树了--注意不能makeroot,因为自动机的 ...
- SPOJ1811 LCS - Longest Common Substring(后缀自动机)
A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the s ...
- 51nod 1600 Simple KMP【后缀自动机+LCT】【思维好题】*
Description 对于一个字符串|S|,我们定义fail[i],表示最大的x使得S[1..x]=S[i-x+1..i],满足(x<i) 显然对于一个字符串,如果我们将每个0<=i&l ...
随机推荐
- Linux_Bash脚本基础
目录 目录 Bash使用基础 if 语句 运算符 逻辑表达式 不将执行指令的结果显示出来 echo 语句 从Bash接受输入参数 Case语句 循环 for 语句 While语句 内置变量和函数 AW ...
- Vagrant 手册之 Vagrantfile - 机器设置 config.vm
原文地址 配置的命名空间:config.vm config.vm 中的设置修改 Vagrant 管理的机器的配置. 1. 可用的设置项 config.vm.boot_timeout Vagrant 等 ...
- 爬虫中GET方法应用基本模型
根据get方法,更改界面url从而获取信息 GET请求URL附带查询参数 POST请求保存在form表单中 分析百度贴吧url特点: 分析url https://tieba.baidu.com/f是贴 ...
- 【SD系列】SAP 跨年时更改销售凭证号码段
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[SD系列]SAP 跨年时更改销售凭证号码段 ...
- poj2431Expedition
A group of cows grabbed a truck and ventured on an expedition deep into the jungle. Being rather poo ...
- Pikachu漏洞练习平台实验——SQL注入(四)
1.概述 1.1发生原因 SQL注入漏洞,主要是开发人员在构建代码时,没有对输入边界进行安全考虑,导致攻击者可以通过合法的输入点提交一些精心构造的语句,从而欺骗后台数据库对其进行执行,导致数据库信息泄 ...
- 【五一qbxt】day5 图论
图论 学好图论的基础: 必须意识到图论hendanteng xuehuifangqi(雾 图 G = (V,E) 一般来说,图的存储难度主要在记录边的信息 无向图的存储中,只需要将一条无向边拆成两条即 ...
- [BZOJ 2653] middle(可持久化线段树+二分答案)
[BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...
- #python# 代理过程中遇到的error
做一下总结 urllib.error.HTTPError: HTTP Error 503: Too many open connections TimeoutError: [WinError 1006 ...
- python学习第四天基本数据类型 int,string,bool
python跟其他编程语言一样,拥有基本的数据类型,计算机 只能识别0101,python是解释语言,有其他的解释器 python整型 int a=10 type(a) "int| pyth ...