Description

懒得写背景了,给你一个字符串init,要求你支持两个操作

(1):在当前字符串的后面插入一个字符串

(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)

你必须在线支持这些操作。

Solution

思路比较直观啊

首先没有插入的话,预处理好每个点 \(|right|\) 就好了

如果有插入的话我们发现实际上就是维护一个子树大小

每一次插入一个节点就相当于把父亲到根路径上的权值全部 \(+1\)

我们用 \(LCT\) 维护这个加边删边和路径加法的操作

每一次询问就是先找到这个串对应的节点 \(x\),如果没找到答案就是 \(0\),否则就是 \(|Right_x|\) 了

这题是有根树,不需要 \(makeroot\) 操作,写起来比较舒服

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+10;
namespace LCT{
int ch[N][2],fa[N],la[N],w[N];
inline bool isrt(int x){return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;}
inline void mark(int x,int t){la[x]+=t;w[x]+=t;}
inline void pushdown(int x){
if(!la[x])return ;
mark(ch[x][0],la[x]);mark(ch[x][1],la[x]);
la[x]=0;
}
inline void rotate(int x){
int y=fa[x];bool t=ch[y][1]==x;
ch[y][t]=ch[x][!t];fa[ch[y][t]]=y;
ch[x][!t]=y;fa[x]=fa[y];
if(!isrt(y))ch[fa[y]][ch[fa[y]][1]==y]=x;
fa[y]=x;
}
inline void Push(int x){
if(!isrt(x))Push(fa[x]);
pushdown(x);
}
inline void splay(int x){
Push(x);
while(!isrt(x)){
int y=fa[x],p=fa[y];
if(isrt(y))rotate(x);
else if((ch[p][0]==y)==(ch[y][0]==x))rotate(y),rotate(x);
else rotate(x),rotate(x);
}
}
inline void access(int x){
int y=0;
while(x)splay(x),ch[x][1]=y,x=fa[y=x];
}
inline void link(int x,int y){
fa[x]=y;access(y);splay(y);splay(x);mark(y,w[x]);
}
inline void cut(int x){
access(x);splay(x);mark(ch[x][0],-w[x]);fa[ch[x][0]]=0;ch[x][0]=0;
}
inline int query(int x){
splay(x);return w[x];
}
}
char s[N],op[10];int Q,mask=0;
inline void decode(){
int len=strlen(s),t=mask;
for(int j=0;j<len;j++){
t=(t*131+j)%len;
swap(s[j],s[t]);
}
}
int ch[N][27],fa[N],len[N],cur=1,cnt=1;
inline void ins(int c){
int p=cur;cur=++cnt;len[cur]=len[p]+1;LCT::w[cur]=1;
for(;p && !ch[p][c];p=fa[p])ch[p][c]=cur;
if(!p)fa[cur]=1,LCT::link(cur,1);
else{
int q=ch[p][c];
if(len[q]==len[p]+1)fa[cur]=q,LCT::link(cur,q);
else{
int nt=++cnt;len[nt]=len[p]+1;
memcpy(ch[nt],ch[q],sizeof(ch[q]));
LCT::cut(q);LCT::link(nt,fa[q]);LCT::link(q,nt);LCT::link(cur,nt);
fa[nt]=fa[q];fa[q]=fa[cur]=nt;
for(;p && ch[p][c]==q;p=fa[p])ch[p][c]=nt;
}
}
}
inline int solve(int len){
int p=1;
for(int i=0;i<len;i++){
int c=s[i]-'A';
if(ch[p][c])p=ch[p][c];
else return 0;
}
return LCT::query(p);
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
cin>>Q;
scanf("%s",s);
for(int i=0,le=strlen(s);i<le;i++)ins(s[i]-'A');
while(Q--){
scanf("%s%s",op,s);
decode();
int len=strlen(s),la;
if(op[0]=='A')for(int i=0;i<len;i++)ins(s[i]-'A');
else printf("%d\n",la=solve(len)),mask^=la;
}
return 0;
}

bzoj 2555: SubString的更多相关文章

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

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

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

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

  3. bzoj 2555 SubString(SAM+LCT)

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

  4. ●BZOJ 2555 SubString

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

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

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

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

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

  7. 【刷题】BZOJ 2555 SubString

    Description 懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支 ...

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

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

  9. BZOJ 2555: SubString 后缀自动机_LCT

    很水的一道题,就是有些细节没注意到. 比如说将调试信息误以为是最终结果而多调了20分钟QAQ ..... 我们注意到,每新加一个节点,改变的是该节点沿着 Parent 走一直走到根节点. 对应的,在 ...

随机推荐

  1. 学生ID查询

    var http = require("http"); var server = http.createServer(function(req,res){ //得到url var ...

  2. Python 线程复习

    修改全局变量,设立flag来避免线程间数据冲突,低效率版 from threading import Thread import time g_num=0 g_flag = 1 def test1() ...

  3. io多路复用(三)

    #!/usr/bin/env python # -*- coding:utf-8 -*- import socket sk1 = socket.socket() sk1.bind(('127.0.0. ...

  4. [Cerc2013]Magical GCD

    https://vjudge.net/problem/UVA-1642 题意:在一个序列中,找出一段连续的序列,使得长度*gcd最大 固定右端点,当左端点从左向右移动时,gcd不变或变大 gcd相同时 ...

  5. SQL语句取多列的最小值(排除0)

    经常遇到获取数据表中多个列的最小值和最大值,例如: 获取这 4个价格的最小值和最大值: SELECT( SELECT min(minPrice) FROM ( VALUES (IIF(MarketSi ...

  6. MQTT和paho(二)socket

    参考链接:http://blog.csdn.net/yangzl2008/article/details/8861069

  7. Linux知识积累(1)awk的使用方法

    参见:http://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858470.html 简介 awk是一个强大的文本分析工具,相对于grep的查找,se ...

  8. Spring Security 入门(1-3-3)Spring Security - logout 退出登录

    要实现退出登录的功能我们需要在 http 元素下定义 logout 元素,这样 Spring Security 将自动为我们添加用于处理退出登录的过滤器 LogoutFilter 到 FilterCh ...

  9. Spring Security 入门(1-4-1)Spring Security - 认证过程

    理解时可结合一下这位老兄的文章:http://www.importnew.com/20612.html 1.Spring Security的认证过程 1.1.登录过程 - 如果用户直接访问登录页面 用 ...

  10. C#微信公众号——消息处理

    ​当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL. 一.接收POST请求,处理XML信息 public void ProcessRequest(HttpC ...