正题

题目链接:https://www.luogu.com.cn/problem/P5212


题目大意

开始一个字符串\(S\),有\(n\)次操作

  1. 在\(S\)末尾加入一个字符串
  2. 询问一个串在\(S\)中出现了多少次

强制在线


解题思路

强制在线的话,只有\(\text{SAM}\)能够支持动态插字符了,但是我们平时统计答案的时候要先做一次拓扑排序然后上传信息。

这里要动态维护\(\text{parents}\)树的话用\(\text{LCT}\)就好了,就是链修改加单点查询,然后因为根是指定的可以少写很多操作。

时间复杂度\(O(\ (n+S)\log |S|)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
const int N=6e5*2+10;
int n,cnt,len[N],fa[N],ch[N][26];
char st[N];
struct LCT{
int t[N][2],lazy[N],w[N],fa[N];
stack<int> s;
bool Nroot(int x)
{return fa[x]&&((t[fa[x]][0]==x)||(t[fa[x]][1]==x));}
bool Direct(int x)
{return t[fa[x]][1]==x;}
void Add(int x,int val)
{if(x)w[x]+=val,lazy[x]+=val;return;}
void PushDown(int x){
if(!lazy[x])return;
if(t[x][0])Add(t[x][0],lazy[x]);
if(t[x][1])Add(t[x][1],lazy[x]);
lazy[x]=0;return;
}
void Rotate(int x){
int y=fa[x],z=fa[y];
int xs=Direct(x),ys=Direct(y);
int w=t[x][xs^1];
if(Nroot(y))t[z][ys]=x;
t[y][xs]=w;t[x][xs^1]=y;
if(w)fa[w]=y;fa[y]=x;fa[x]=z;
return;
}
void Splay(int x){
int y=x;s.push(x);
while(Nroot(y))y=fa[y],s.push(y);
while(!s.empty())PushDown(s.top()),s.pop();
while(Nroot(x)){
y=fa[x];
if(!Nroot(y))Rotate(x);
else if(Direct(y)==Direct(x))
Rotate(y),Rotate(x);
else Rotate(x),Rotate(x);
}
return;
}
void Access(int x){
for(int y=0;x;y=x,x=fa[x])
Splay(x),t[x][1]=y;
return;
}
void Link(int x,int y)//x为单点,y为树
{fa[x]=y;Access(y);Splay(y);Add(y,w[x]);return;}
void Cut(int x)//将x切断为单点
{Access(x);Splay(x);Add(t[x][0],-w[x]);fa[t[x][0]]=0;t[x][0]=0;return;}
}T;
void decode(char *s,int l,int mask) {
for (int j=0;j<l;j++) {
mask=(mask*131+j)%l;
swap(s[j],s[mask]);
}
return;
}
int insert(int c,int p){
int np=++cnt;len[np]=len[p]+1;T.w[np]++;
for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
if(!p)fa[np]=1,T.Link(np,1);
else{
int q=ch[p][c];
if(len[p]+1==len[q])fa[np]=q,T.Link(np,q);
else{
int nq=++cnt;len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
fa[nq]=fa[q];fa[np]=fa[q]=nq;
T.Cut(q);T.Link(nq,fa[nq]);
T.Link(np,nq);T.Link(q,nq);
for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq;
}
}
return np;
}
int main()
{
scanf("%d",&n);
scanf("%s",st);int l=strlen(st);
int p=cnt=1;int mask=0;
for(int i=0;i<l;i++)
p=insert(st[i]-'A',p);
while(n--){
char op[5];
scanf("%s %s",op,st);l=strlen(st);
decode(st,l,mask);
if(op[0]=='Q'){
int x=1;
for(int i=0;i<l;i++)
if(!ch[x][st[i]-'A'])
{x=0;break;}
else x=ch[x][st[i]-'A'];
if(!x)puts("0");
else{
T.Splay(x);
printf("%d\n",T.w[x]);
mask^=T.w[x];
}
}
else{
for(int i=0;i<l;i++)
p=insert(st[i]-'A',p);
}
}
return 0;
}

P5212-SubString【LCT,SAM】的更多相关文章

  1. 【BZOJ1036】【LCT版】树的统计Count

    Description 一 棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. ...

  2. 2594. [WC2006]水管局长数据加强版【LCT+最小生成树】

    Description SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公司找到一 ...

  3. bzoj 4032: [HEOI2015]最短不公共子串【dp+SAM】

    第一.二问: 就是最小的最长公共长度+1,设f[i][j]为a匹配到i,b匹配到j,第一问的转移是f[i][j]=(a[i]==b[j]?f[i-1][j-1]+1:0),第二问的转移是f[i][j] ...

  4. bzoj 2780: [Spoj]8093 Sevenk Love Oimaster【广义SAM】

    AC自动机比较简单,把询问串做成AC自动机然后模板串边跑变更新即可 SAM是把模板串做成广义SAM,然后每个节点存有几个模板串经过,具体方法是每次更新暴力向上跳直到有时间戳我不会证为什么时间复杂度是对 ...

  5. SPOJ-LCS Longest Common Substring 【后缀自动机】

    题目分析: 用没出现过的字符搞拼接.搞出right树,找right集合的最小和最大.如果最小和最大分居两侧可以更新答案. 代码: #include<bits/stdc++.h> using ...

  6. Codeforces 919D Substring 【拓扑排序】+【DP】

    <题目链接> 题目大意:有一个具有n个节点,m条边的有向图,每个点对应一个小写字母,现在给出每个顶点对应的字母以及有向边的连接情况,求经过的某一条路上相同字母出现的最多次数.如果次数无限大 ...

  7. 【算法专题】后缀自动机SAM

    后缀自动机是用于识别子串的自动机. 学习推荐:陈立杰讲稿,本文记录重点部分和感性理解(论文语言比较严格). 刷题推荐:[后缀自动机初探],题目都来自BZOJ. [Right集合] 后缀自动机真正优于后 ...

  8. BZOJ2555 SubString 【后缀自动机 + LCT】

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

  9. ZJOI2012网络 题解报告【LCT】

    题目描述 有一个无向图G,每个点有个权值,每条边有一个颜色.这个无向图满足以下两个条件: 对于任意节点连出去的边中,相同颜色的边不超过两条. 图中不存在同色的环,同色的环指相同颜色的边构成的环. 在这 ...

随机推荐

  1. zoolkeeper 的Curator的分布式锁

    RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3) CuratorFramework client = CuratorFram ...

  2. new Vue({ render: h => h(App), }).$mount('#app')

    这里创建的vue实例没有el属性,而是在实例后面添加了一个$mount('#app')方法. $mount('#app') :手动挂载到id为app的dom中的意思 当Vue实例没有el属性时,则该实 ...

  3. Redis笔记(一)

    redis:1.什么是缓存? mybatis一级缓存和二级缓存 mybatis的一级缓存存在哪? SqlSession,就不会再走数据库 什么情况下一级缓存会失效? 当被更新,删除的时候sqlsess ...

  4. Django——ORM打印SQL

    如果想打印ORM转换过程中的SQL,需要在settings.py中进行如下配置: LOGGING = { 'version': 1, 'disable_existing_loggers': False ...

  5. jq的slideToggle效果

    slideToggle() 方法通过使用滑动效果(高度变化)来切换元素的可见状态. 如果被选元素是可见的,则隐藏这些元素,如果被选元素是隐藏的,则显示这些元素. 例子:一个简单的下拉菜单效果----& ...

  6. elementui table的新增,编辑和删除

    \ 新增 this.tableData.unshift(data); 编辑 this.$set(this.tableData,data.index,data); 删除 rows.splice(inde ...

  7. (1)java Spring Cloud+Spring boot+mybatis企业快速开发架构之微服务是什么?它的优缺点有哪些?

    ​ "微服务"一词来源于 Martin Fowler 的<Microservices>一文.微服务是一种架构风格,即将单体应用划分为小型的服务单元,微服务之间使用 HT ...

  8. io流-缓冲流

    单独去数据时,数据按块读入缓冲区,其后的操作则直接访问缓冲区 但是用 BufferedInputStream读取字节文件时,

  9. 珠峰2016,第9期 vue.js 笔记部份

    在珠峰参加培训好年了,笔记原是记在本子上,现在也经不需要看了,搬家不想带上书和本了,所以把笔记整理下,存在博客中,也顺便复习一下 安装vue.js 因为方便打包和环境依赖,所以建意npm  init  ...

  10. Vue项目中应用TypeScript

    一.前言 与如何在React项目中应用TypeScript类似 在VUE项目中应用typescript,我们需要引入一个库vue-property-decorator, 其是基于vue-class-c ...