BZOJ2555 SubString(后缀自动机+LCT)
询问串放在SAM上不跳fail跑到的节点的|right|即为答案。用LCT维护parent树即可。可以直接维护子树信息,也可以转化为路径加。注意强制在线所使用的mask是作为参数传进去的。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 1300010
#define lson tree[k].ch[0]
#define rson tree[k].ch[1]
#define lself tree[tree[k].fa].ch[0]
#define rself tree[tree[k].fa].ch[1]
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int Q,n,m,cnt=1,last=1,son[N][26],fail[N],len[N],mask;
char s[N],t[N];
struct data{int ch[2],fa,rev,s,sv,x;
}tree[N];
void up(int k){tree[k].s=tree[k].sv+tree[lson].s+tree[rson].s+tree[k].x;}
void rev(int k){if (k) swap(lson,rson),tree[k].rev^=1;}
void down(int k){if (tree[k].rev) rev(lson),rev(rson),tree[k].rev=0;}
int whichson(int k){return rself==k;}
bool isroot(int k){return lself!=k&&rself!=k;}
void push(int k){if (!isroot(k)) push(tree[k].fa);down(k);}
void move(int k)
{
int fa=tree[k].fa,gf=tree[fa].fa,p=whichson(k);
if (!isroot(fa)) tree[gf].ch[whichson(fa)]=k;tree[k].fa=gf;
tree[fa].ch[p]=tree[k].ch[!p],tree[tree[k].ch[!p]].fa=fa;
tree[k].ch[!p]=fa,tree[fa].fa=k;
up(fa),up(k);
}
void splay(int k)
{
push(k);
while (!isroot(k))
{
int fa=tree[k].fa;
if (!isroot(fa))
if (whichson(fa)^whichson(k)) move(k);
else move(fa);
move(k);
}
}
void access(int k)
{
for (int t=0;k;t=k,k=tree[k].fa)
{
splay(k);
tree[k].sv+=tree[rson].s-tree[t].s;
rson=t;
up(k);
}
}
void makeroot(int k){access(k),splay(k),rev(k);}
void link(int x,int y){makeroot(x);access(y),splay(y);tree[x].fa=y;tree[y].sv+=tree[x].s;up(y);}
void cut(int x,int y){makeroot(x),access(y),splay(y);tree[y].ch[0]=tree[x].fa=0;up(y);}
int query(int k){if (!k) return 0;makeroot(1);access(k),splay(k);return tree[k].s-tree[lson].s;}
void decode(int mask)
{
for (int j=0;j<m;j++)
{
mask=(mask*131+j)%m;
char u=t[j];t[j]=t[mask];t[mask]=u;
}
}
void relink(int x,int y)
{
if (fail[x]) cut(x,fail[x]);
fail[x]=y;link(x,y);
}
void ins(int c)
{
int x=++cnt,p=last;len[x]=len[p]+1;last=x;tree[x].x=tree[x].s=1;
while (!son[p][c]&&p) son[p][c]=x,p=fail[p];
if (!p) relink(x,1);
else
{
int q=son[p][c];
if (len[p]+1==len[q]) relink(x,q);
else
{
int y=++cnt;
len[y]=len[p]+1;
memcpy(son[y],son[q],sizeof(son[q]));
relink(y,fail[q]);
relink(q,y);
relink(x,y);
while (son[p][c]==q) son[p][c]=y,p=fail[p];
}
}
}
int run(char *s)
{
int k=1;
for (int i=0;i<m;i++) k=son[k][s[i]-'A'];
return k;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
Q=read();scanf("%s",s);n=strlen(s);
for (int i=0;i<n;i++) ins(s[i]-'A');
while (Q--)
{
scanf("%s",t);
if (t[0]=='A')
{
scanf("%s",t);m=strlen(t);
decode(mask);
for (int i=0;i<m;i++) ins(t[i]-'A');
}
else
{
scanf("%s",t);m=strlen(t);
decode(mask);
int ans=query(run(t));
printf("%d\n",ans);
mask^=ans;
}
}
return 0;
}
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 ...
随机推荐
- Lasso回归的坐标下降法推导
目标函数 Lasso相当于带有L1正则化项的线性回归.先看下目标函数:RSS(w)+λ∥w∥1=∑Ni=0(yi−∑Dj=0wjhj(xi))2+λ∑Dj=0∣wj∣RSS(w)+λ∥w∥1=∑i=0 ...
- 在不切换分支的情况下,如何在all branches中快速查看指定分支,相对其他分支的状态
假设需要查看的分支为temp 1.git show temp 通过这个可以拿到commit id 2.查看TortoiseGit的日志,左下角勾选所有分支 3.在日志界面搜索commit id,然后右 ...
- 简略描述:一个 url 从输入按下回车键,到页面展示出来,都经历了什么?
首先,在输入网址按下回车以后,这个时候DNS服务器会通过当前的网址去解析网址的 ip: 在查找到真的 IP 以后,这个时候浏览器会向 web 服务器发起一个 tcp 连接请求(三次握手): 第一次:建 ...
- osg模型部分节点旋转
osg::ref_ptr<osg::Geode> CreateBox() { osg::ref_ptr<osg::Geode> geode = new osg::Geode; ...
- 22Flutter中的常见的按钮组件 以及自定义按钮组件
/* Flutter中的常见的按钮组件 以及自定义按钮组件 一.Flutter中的按钮组件介绍 Flutter里有很多的Button组件,常见的按钮组件有:RaisedButton/FlatButto ...
- 阶段5 3.微服务项目【学成在线】_day09 课程预览 Eureka Feign_05-Feign远程调用-客户端负载均衡介绍
2 Feign远程调用 在前后端分离架构中,服务层被拆分成了很多的微服务,服务与服务之间难免发生交互,比如:课程发布需要调用 CMS服务生成课程静态化页面,本节研究微服务远程调用所使用的技术. 下图是 ...
- 阶段5 3.微服务项目【学成在线】_day17 用户认证 Zuul_05-用户认证-认证服务查询数据库-调用查询用户接口
用户认证服务调用根据账号查询用户的信息 怎么远程调用呢?要创建一个客户端,这个客户端其实就是一个接口 标明服务的名称是ucenter服务 这是ucenter服务里面 复制过来接口的定义,GetMapp ...
- 阶段5 3.微服务项目【学成在线】_day16 Spring Security Oauth2_18-认证接口开发-接口开发-service
定义AuthController 实现刚才写的api接口 controller定义热requestMapping 是 / 就可以了. 因为我们的登陆跟路径就是/auth. 这样到login就是 /au ...
- java写文件实现换行
Java 写文件实现换行 第一种: 写入的内容中利用\r\n进行换行 File file = new File("D:/text"); try { if(!file.exist ...
- LeetCode_58. Length of Last Word
58. Length of Last Word Easy Given a string s consists of upper/lower-case alphabets and empty space ...