喜闻乐见的LCT+SAM

此题要求动态插入,直接上后缀树。然后询问其实就是求一个节点的子树后缀结束节点的个数。

因为建立后缀树需要插入和删除,就直接上LCT。每次加入一个点,把它到根的路径加一

(现在我才知道access之后那个splay就是这个点到根的路径,LCT学得不好)

思路不需要说太多,就是码量大。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=3001000;
int T,ans;
char s[N];
int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return sum*f;
}
int get(int ans){
cin>>s;
int len=strlen(s);
for (int j=0;j<len;j++) {
ans=(ans*131+j)%len;
char c=s[j];
s[j]=s[ans];
s[ans]=c;
}
return len;
}
struct lct{
int fa[N],ch[N][2],w[N],lazy[N],stack[N];
void add(int x,int y){
w[x]+=y;lazy[x]+=y;
}
void pushdown(int x){
if(lazy[x]){
add(ch[x][0],lazy[x]);add(ch[x][1],lazy[x]);
lazy[x]=0;
}
}
bool isroot(int x){
return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
}
bool son(int x){
return ch[fa[x]][1]==x;
}
void rotate(int x){
int y=fa[x],z=fa[y],a=son(x),b=son(y),c=ch[x][!a];
if(!isroot(y))ch[z][b]=x;fa[x]=z;
if(c)fa[c]=y;ch[y][a]=c;
ch[x][!a]=y;fa[y]=x;
}
void splay(int x){
int top=1,a=x;stack[top]=a;
while(a)stack[++top]=a=fa[a];
while(top)pushdown(stack[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(isroot(y))rotate(x);
else{
if(son(x)==son(y))rotate(y);
else rotate(x);
rotate(x);
}
}
}
void access(int x){
for(int j=0;x;j=x,x=fa[x])
splay(x),ch[x][1]=j;
}
void link(int x,int f){
fa[x]=f;access(f);splay(f);add(f,w[x]);
}
void cut(int x){
access(x);splay(x);add(ch[x][0],-w[x]);
fa[ch[x][0]]=0;ch[x][0]=0;
}
}t;
struct SAM{
int tot,u,ln[N],size[N],trans[N][27],fa[N];
void ins(int c){
int x=++tot;ln[x]=ln[u]+1;size[x]=1;
t.w[x]=1;
for(;u&&trans[u][c]==0;u=fa[u])trans[u][c]=x;
if(u==0)fa[x]=1,t.link(x,1);
else{
int v=trans[u][c];
if(ln[v]==ln[u]+1)fa[x]=v,t.link(x,v);
else{
int w=++tot;
ln[w]=ln[u]+1;fa[w]=fa[v];
t.link(w,fa[w]);
memcpy(trans[w],trans[v],sizeof(trans[w]));
fa[x]=fa[v]=w;
t.cut(v);t.link(v,w);t.link(x,w);
for(;u&&trans[u][c]==v;u=fa[u])trans[u][c]=w;
}
}
u=x;
}
void add(){
int len=get(ans);
for(int i=0;i<len;i++)ins(s[i]-'A'+1);
}
int check(){
int len=get(ans);
int now=1;
for(int i=0;i<len;i++){
if(trans[now][s[i]-'A'+1]==0)return 0;
now=trans[now][s[i]-'A'+1];
}
t.splay(now);
return t.w[now];
}
}sam;
int main(){
T=read();
sam.tot=sam.u=1;
cin>>s;
int len=strlen(s);
for(int i=0;i<len;i++)sam.ins(s[i]-'A'+1);
while(T--){
cin>>s;
if(s[0]=='Q'){
int tmp=sam.check();
printf("%d\n",tmp);
ans^=tmp;
}
else sam.add();
}
return 0;
}

BZOJ 2555 SubString(LCT+后缀树)的更多相关文章

  1. bzoj 2555: SubString【后缀自动机+LCT】

    一直WA--找了半天错的发现居然是解密那里的mask其实是不能动的--传进去的会变,但是真实的那个不会变-- 然后就是后缀自动机,用LCT维护parent树了--注意不能makeroot,因为自动机的 ...

  2. bzoj 2555: SubString 后缀自动机+LCT

    2555: SubString Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 688  Solved: 235[Submit][Status][Dis ...

  3. 字符串(LCT,后缀自动机):BZOJ 2555 SubString

    2555: SubString Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1620  Solved: 471 Description 懒得写背景了 ...

  4. ●BZOJ 2555 SubString

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2555题解: 后缀自动机+LCT 不难发现,对于输入的询问串,在自动机里trans后的到的状态 ...

  5. 2555: SubString[LCT+SAM]

    2555: SubString Time Limit: 30 Sec  Memory Limit: 512 MB Submit: 2601  Solved: 780 [Submit][Status][ ...

  6. [BZOJ2555]SubString LCT+后缀自动机

    2555: SubString Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 3253  Solved: 975[Submit][Status][Di ...

  7. bzoj 2555 SubString —— 后缀自动机+LCT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555 建立后缀自动机,就可以直接加入新串了: 出现次数就是 Right 集合的大小,需要查询 ...

  8. bzoj 2555 SubString——后缀自动机+LCT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555 要维护 right 集合的大小.因为 fa 会变,且 fa 构成一棵树,所以考虑用 L ...

  9. bzoj 2555 SubString(SAM+LCT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2555 [题意] 给定一个字符串,可以随时插入字符串,提供查询s在其中作为连续子串的出现 ...

随机推荐

  1. TESTUSERB 仅能对TESTUSERA 用户下的某些表增删改查、有些表仅能对某些列update,查询TESTUSERB 用户权限,获取批量赋予语句。

    TESTUSERB 仅能对TESTUSERA 用户下的某些表增删改查.有些表仅能对某些列update,查询TESTUSERB 用户权限,获取批量赋予语句. select 'grant '|| PRIV ...

  2. ZBrush为电影制作设计独特的生物概念

    任何一个从事3D行业的艺术家,在雕刻和画画方面,都要有牢固的基本技能,还要会使用一些软件.比如今天我们提到的这位概念设计师.插画师和艺术导演Ian Joyner,他在创作新角色之前,都会思考如何以及为 ...

  3. Codeforces Round #499 (Div. 2) D. Rocket_交互题_二分

    第一次作交互题,有点不习惯. 由于序列是循环的,我们可以将一半的机会用于判断当前是否是在说谎,另一半的机会用于二分的判断. 对于判断是否实在说谎,用1判断即可.因为不可能有比1还小的数. 本题虽然非常 ...

  4. Pyhton学习——Day59

    参考博客: http://www.cnblogs.com/wupeiqi/articles/6144178.html Form 1. 验证 2. 生成HTML(保留上次输入内容) 3. 初始化默认是 ...

  5. Python 爬歌曲

    Python 爬歌曲 小练习 import re import time import requests # http://www.htqyy,com/top/hot # http://f2.htqy ...

  6. 如何打印枚举类型:%d

    #include <stdio.h> typedef enum SessionState { SESSION_OPENING, /* Session scope is being crea ...

  7. laravel :Call to undefined function App\Http\Controllers\success() 解决方法

    今天在调用方法时,报错如下:Call to undefined function App\Http\Controllers\success():方法已定义好了,所以我怀疑是未引入function.ph ...

  8. 使用剩余参数代替 arguments (prefer-rest-params)

    使用剩余参数代替 arguments (prefer-rest-params) 剩余参数来自于ES2016.可以在可变函数中使用这个特性来替代arguments变量. arguments没有Array ...

  9. Java二维码打印

    http://blog.csdn.net/OnePersonTZ/article/details/66560513

  10. ASP.NET-HTML.Helper常用方法

    Html.ActionLink方法 Html.ActionLink("linkText","actionName") Html.ActionLink(" ...