【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 ...
随机推荐
- MySQL - 修改数据库文件物理路径
一共两步: 修改my.ini文件的datadir: 将修改前datadir路径下的文件复制到修改后的datadir路径. 注意: my.ini可能有多个,windows 系统可以在 MySQL 服务的 ...
- elasticsearch安装分词插件
在常用的中文分词器.拼音分词器.繁简体转换插件.国内用的就多的分别是:elasticsearch-analysis-ikelasticsearch-analysis-pinyinelasticsear ...
- gradle命令行打包不同环境的apk包
为什么我搜这个? 因为 早上在开发那边我看到他控制不同环境就是在这个下拉框选择不同的环境的 搜索词: Gradle 入门--只此一篇 https://www.jianshu.com/p/001abe1 ...
- Fiddler抓包ios亲测
1 打开Fiddler设置端口 2 设置可以抓取https选项 3 手机连接WIFI和电脑处于同一局域网并设置代理端口和fiddler中设置一致 4 证书安装手机浏览器输入代理电脑ip及端口如192. ...
- poj1163The Triangle(动态规划,记忆化搜索)
7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 (Figure 1) Figure 1 shows a number triangle. Write a program that calc ...
- hdu1257最少拦截系统 动态规划(最长递增子序列(LIS))
Problem Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高 ...
- 机器学习实战笔记-10-K均值聚类
K-均值聚类 优点:易实现.缺点:可能收敛到局部最小值,大规模数据集上收敛较慢:适用于数值型数据. K-均值聚类(找到给定数据集的k个簇) 算法流程 伪代码: 创建k个点作为起始质心(经常是随机选择) ...
- linux flock()
表头文件 #include<sys/file.h> 定义函数 int flock(int fd,int operation); 函数说明 flock()会依参数operation所指 ...
- Js类的静态方法与实例方法区分以及jQuery如何拓展两种方法
上学时C#老师讲到对象有两类方法,静态方法(Static)和实例方法(非Static),当时不理解静态是为何意,只是强记. 后来从事前端工作,一直在对类(即对象,Js中严格来说没有类的定义,虽众所周知 ...
- 牛逼哄哄的 API 网关是什么鬼?面试必问!
Java技术栈 www.javastack.cn 优秀的Java技术公众号 作者:aCoder2013 github.com/aCoder2013/blog/issues/35 前言 假设你正在开发一 ...