【BZOJ2555】SubString(后缀自动机,Link-Cut Tree)
【BZOJ2555】SubString(后缀自动机,Link-Cut Tree)
题面
题解
这题看起来不难
每次要求的就是\(right/endpos\)集合的大小
所以搞一个\(LCT\)维护一下\(SAM\)的\(Parent\)树就好了
但是代码一点都不好写(我还是对着黄学长的调的。。。)
于是乎我也学着魔改了一下\(LCT\)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define MAX 600006
char ch[MAX];
inline int read()
{
int x=0,t=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int mask,ans;
struct LCT
{
#define lson (t[x].ch[0])
#define rson (t[x].ch[1])
struct Node
{
int ch[2],ff;
int rev,v,ly;
}t[MAX<<1];
int S[MAX<<1],top;
bool isroot(int x){return t[t[x].ff].ch[0]!=x&&t[t[x].ff].ch[1]!=x;}
void rotate(int x)
{
int y=t[x].ff,z=t[y].ff;
int k=t[y].ch[1]==x;
if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y;
t[x].ch[k^1]=y;t[y].ff=x;
}
void putrev(int x){swap(lson,rson);t[x].rev^=1;}
void putly(int x,int v){t[x].v+=v;t[x].ly+=v;}
void pushdown(int x)
{
if(t[x].rev)
{
if(lson)putrev(lson);
if(rson)putrev(rson);
t[x].rev^=1;
}
if(t[x].ly!=0)
{
if(lson)putly(lson,t[x].ly);
if(rson)putly(rson,t[x].ly);
t[x].ly=0;
}
}
void Splay(int x)
{
S[top=1]=x;
for(int i=x;!isroot(i);i=t[i].ff)S[++top]=t[i].ff;
while(top)pushdown(S[top--]);
while(!isroot(x))
{
int y=t[x].ff,z=t[y].ff;
if(!isroot(y))
(t[z].ch[1]==y)^(t[y].ch[1]==x)?rotate(x):rotate(y);
rotate(x);
}
}
void access(int x){for(int y=0;x;y=x,x=t[x].ff)Splay(x),rson=y;}
void makeroot(int x){access(x);Splay(x);putrev(x);}
void split(int x,int y){makeroot(x);access(y);Splay(y);}
void cut(int x){access(x);Splay(x);putly(lson,-t[x].v);t[lson].ff=0;lson=0;}
void link(int x,int f){t[x].ff=f;access(f);Splay(f);putly(f,t[x].v);}
int findroot(int x){access(x);Splay(x);while(lson)x=lson;return x;}
}LCT;
struct SAM
{
struct Node
{
int son[26];
int ff,len;
}t[MAX<<1];
int last,tot;
void init(){last=tot=1;}
void extend(int c)
{
int p=last,np=++tot;last=np;LCT.t[np].v=1;
while(p&&!t[p].son[c])t[p].son[c]=np,p=t[p].ff;
if(!p)t[np].ff=1,LCT.link(np,1);
else
{
int q=t[p].son[c];
if(t[q].len==t[p].len+1)t[np].ff=q,LCT.link(np,q);
else
{
int nq=++tot;
t[nq]=t[q];
t[nq].len=t[p].len+1;
LCT.link(nq,t[q].ff);
t[q].ff=t[np].ff=nq;
LCT.cut(q);LCT.link(q,nq);LCT.link(np,nq);
while(p&&t[p].son[c]==q)t[p].son[c]=nq,p=t[p].ff;
}
}
}
}SAM;
void Decode(char *ch,int mask)
{
int l=strlen(ch);
for(int i=0;i<l;++i)
{
mask=(mask*131+i)%l;
swap(ch[i],ch[mask]);
}
}
int main()
{
int Q=read();
SAM.init();
scanf("%s",ch+1);
for(int i=1,l=strlen(ch+1);i<=l;++i)SAM.extend(ch[i]-'A');
while(Q--)
{
scanf("%s",ch);
if(ch[0]=='A')
{
scanf("%s",ch+1);
Decode(ch+1,mask);
for(int i=1,l=strlen(ch+1);i<=l;++i)SAM.extend(ch[i]-'A');
}
else
{
scanf("%s",ch+1);
Decode(ch+1,mask);
int now=1;
for(int i=1,l=strlen(ch+1);i<=l;++i)
now=SAM.t[now].son[ch[i]-'A'];
if(!now)printf("%d\n",ans=0);
else
{
LCT.Splay(now);
printf("%d\n",ans=LCT.t[now].v);
}
mask^=ans;
}
}
return 0;
}
【BZOJ2555】SubString(后缀自动机,Link-Cut Tree)的更多相关文章
- BZOJ2555 SubString【SAM + Link Cut Tree】
BZOJ2555. SubString 要求在线询问一个串在原串中出现的次数,并且可以在原串末尾添加字符串 如果没有修改的话,考虑建出\(parent\)树之后统计每个\(endpos\)节点的\(r ...
- luogu5212/bzoj2555 substring(后缀自动机+动态树)
对字符串构建一个后缀自动机. 每次查询的就是在转移边上得到节点的parent树中后缀节点数量. 由于强制在线,可以用动态树维护后缀自动机parent树的子树和. 注意一个玄学的优化:每次在执行连边操作 ...
- link cut tree 入门
鉴于最近写bzoj还有51nod都出现写不动的现象,决定学习一波厉害的算法/数据结构. link cut tree:研究popoqqq那个神ppt. bzoj1036:维护access操作就可以了. ...
- Codeforces Round #339 (Div. 2) A. Link/Cut Tree 水题
A. Link/Cut Tree 题目连接: http://www.codeforces.com/contest/614/problem/A Description Programmer Rostis ...
- Link/cut Tree
Link/cut Tree 一棵link/cut tree是一种用以表示一个森林,一个有根树集合的数据结构.它提供以下操作: 向森林中加入一棵只有一个点的树. 将一个点及其子树从其所在的树上断开. 将 ...
- 洛谷P3690 Link Cut Tree (模板)
Link Cut Tree 刚开始写了个指针版..调了一天然后放弃了.. 最后还是学了黄学长的板子!! #include <bits/stdc++.h> #define INF 0x3f3 ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- bzoj2049 [Sdoi2008]Cave 洞穴勘测 link cut tree入门
link cut tree入门题 首先说明本人只会写自底向上的数组版(都说了不写指针.不写自顶向下QAQ……) 突然发现link cut tree不难写... 说一下各个函数作用: bool isro ...
- P3690 【模板】Link Cut Tree (动态树)
P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...
随机推荐
- ubuntu下smb的配置
PS: 转自Ubuntu中文论坛 -------------------------------------------------------------------------------- ...
- mongodb 学习二
基本操作 增删改查实一个数据库必备的操作,接下来我们就说说怎么在shell下进行增删改查. 我们另外打开一个"命令指示符"窗口(注意:之前的不能关闭),输入mongo打开Mongo ...
- LeetCode - 690. Employee Importance
You are given a data structure of employee information, which includes the employee's unique id, his ...
- 关闭sublime自动检测更新提示
在使用sublime text 3的时候,有自动更新的话再打开的时候总是提醒更新,这让我这个强迫症重度患者非常难受,要取消自动检查更新,点击菜单栏"Preferences"=> ...
- vagrant系列教程(一):vagrant的安装与初识(转)
[参考]https://github.com/astaxie/go-best-practice/blob/master/ebook/zh/01.1.md 阅读目录 下载一个合适的box 完成一个box ...
- POJ 1021 2D-Nim
Description The 2D-Nim board game is played on a grid, with pieces on the grid points. On each move, ...
- Ajax检测用户名是否已经注册
程序功能 当用户名输入完成(即用户名输入框失去焦点),利用Ajax检测用户名是否已经注册! 实现过程 利用Ajax向CheckUserServlet发送请求,判断该用户名是否可用.这里只是为了演示Aj ...
- Android WebView 保持登录问题
最近有个需求是这样的:在应用中添加一个商城,商城的实现是H5(包括登录).需要将这个H5嵌到原生应用中,并在原生代码中添加支付功能. 接到这个需求的时候,想这不是很简单么,用WebView加载这个页面 ...
- python介绍篇
二进制编码ASSIC 每一个字符统一都需要8个bit来存储 计算机容量 1位 = 1bit 8bit = 1byte = 1字节 1024bytes = 1kbytes =1KB 1024个字符,小文 ...
- vscode格式化Vue出现的问题
一.VSCode中使用vetur插件格式化vue文件时,js代码会自动加上冒号和分号 本来就是简写比较方便舒服,结果一个格式化回到解放前 最后找到问题原因: 首先,vetur默认设置是这个样的.也就是 ...