【bzoj2555】 SubString
http://www.lydsy.com/JudgeOnline/problem.php?id=2555 (题目链接)
题意
给出一个初始串,维护两个操作。在原串后面加入一个字符串;询问某个字符串在原串中出现的次数。强制在线。
Solution
对于加入操作,我们动态构造后缀自动机,每次就将添加的节点${parent}$树上到根节点的路径上的节点的${right}$集合大小全部加${1}$。树上路径区间加法,有因为这是个动态树,所以我们用${LCT}$维护${parent}$树就可以了。
细节
坑死了,解码过程中${mask}$是不变的,只有在询问之后才会异或上答案发生改变。幸好看了${PoPoQQQ}$大爷的博客→_→
代码
// bzoj2555
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#define RG register
#define LL long long
#define inf (1ll<<30)
#define MOD 1000000007
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=600010,maxm=3000010;
char s[maxm];
int Q,mask,r[maxn<<1]; namespace LCT {
int tr[maxn<<1][2],fa[maxn<<1],tag[maxn<<1]; void pushdown(int x) {
if (tr[fa[x]][0]==x || tr[fa[x]][1]==x) pushdown(fa[x]);
if (tag[x]) {
r[tr[x][0]]+=tag[x];tag[tr[x][0]]+=tag[x];
r[tr[x][1]]+=tag[x];tag[tr[x][1]]+=tag[x];
tag[x]=0;
}
}
void rotate(int x) {
int y=fa[x],z=fa[y],l,r;
l=tr[y][1]==x;r=l^1;
if (tr[z][0]==y || tr[z][1]==y) tr[z][tr[z][1]==y]=x;
fa[x]=z;fa[y]=x;fa[tr[x][r]]=y;
tr[y][l]=tr[x][r];tr[x][r]=y;
}
void splay(int x) {
pushdown(x);
while (tr[fa[x]][0]==x || tr[fa[x]][1]==x) {
int y=fa[x],z=fa[y];
if (tr[z][0]==y || tr[z][1]==y) {
if (tr[z][0]==y ^ tr[y][0]==x) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x) {
for (int y=0;x;y=x,x=fa[x])
splay(x),tr[x][1]=y;
}
void add(int x,int val) {
r[x]+=val;tag[x]+=val;
}
void link(int x,int y) {
access(y);splay(y);add(y,r[x]);
fa[x]=y;
}
void cut(int x) {
access(x);splay(x);add(tr[x][0],-r[x]);
tr[x][0]=fa[tr[x][0]]=0;
}
int query(int x) {
splay(x);return r[x];
}
}
using namespace LCT; namespace SAM {
int Dargen,last,sz;
int len[maxn<<1],ch[maxn<<1][26],par[maxn<<1];
void Init() {Dargen=last=sz=1;}
void Extend(int c) {
int np=++sz,p=last;last=np;
len[np]=len[p]+1;r[np]=1;
for (;p && !ch[p][c];p=par[p]) ch[p][c]=np;
if (!p) par[np]=Dargen,link(np,Dargen);
else {
int q=ch[p][c];
if (len[p]+1==len[q]) par[np]=q,link(np,q);
else {
int nq=++sz;len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
par[nq]=par[q],link(nq,par[q]);
par[np]=par[q]=nq;
cut(q),link(np,nq),link(q,nq);
for (;p && ch[p][c]==q;p=par[p]) ch[p][c]=nq;
}
}
}
int match(char *r) {
int p=Dargen,l=strlen(r);
for (int i=0;i<l;i++) {
if (!ch[p][r[i]-'A']) return 0;
p=ch[p][r[i]-'A'];
}
return query(p);
}
}
using namespace SAM; void decode(char *r,int t) {
int len=strlen(r);
for (int j=0;j<len;j++) {
t=(t*131+j)%len;
swap(r[j],r[t]);
}
}
int main() {
scanf("%d",&Q);
scanf("%s",s+1);
Init();
int n=strlen(s+1);
for (int i=1;i<=n;i++) Extend(s[i]-'A');
char ch[10];mask=0;
while (Q--) {
scanf("%s%s",ch,s);
decode(s,mask);
n=strlen(s);
if (ch[0]=='A') for (int i=0;i<n;i++) Extend(s[i]-'A');
if (ch[0]=='Q') {
int ans=match(s);
mask^=ans;
printf("%d\n",ans);
}
}
return 0;
}
【bzoj2555】 SubString的更多相关文章
- 【BZOJ2555】SubString(后缀自动机,Link-Cut Tree)
[BZOJ2555]SubString(后缀自动机,Link-Cut Tree) 题面 BZOJ 题解 这题看起来不难 每次要求的就是\(right/endpos\)集合的大小 所以搞一个\(LCT\ ...
- 【BZOJ2555】SubString 后缀自动机+LCT
[BZOJ2555]SubString Description 懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2 ...
- 【BZOJ-2555】SubString 后缀自动机 + LinkCutTree
2555: SubString Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 1936 Solved: 551[Submit][Status][Di ...
- 【BZOJ2555】SubString
算是学会sam了吧…… 原题: 懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了 ...
- 【BZOJ2555】SubString(后缀自动机,LCT)
题意:给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支持这些操作. 长度 <= ...
- 【leetcode】Substring with Concatenation of All Words
Substring with Concatenation of All Words You are given a string, S, and a list of words, L, that ar ...
- 【leetcode】Substring with Concatenation of All Words (hard) ★
You are given a string, S, and a list of words, L, that are all of the same length. Find all startin ...
- 【LeetCode】哈希表 hash_table(共88题)
[1]Two Sum (2018年11月9日,k-sum专题,算法群衍生题) 给了一个数组 nums, 和一个 target 数字,要求返回一个下标的 pair, 使得这两个元素相加等于 target ...
- 【LeetCode】字符串 string(共112题)
[3]Longest Substring Without Repeating Characters (2019年1月22日,复习) [5]Longest Palindromic Substring ( ...
随机推荐
- bootstrap switch样式修改与多列等间距布局
先以一张图开启今天的随笔 今天实习遇到了switch按钮,小姐姐说用插件bootstrap switch来写,我第一次用这个插件,首先在引入方面就遇到了很多坑,先来总结一下bootstrap swit ...
- Linux常用压缩解压命令
tar命令 解包:tar zxvf FileName.tar 打包:tar czvf FileName.tar DirName gz命令 解压1:gunzip FileName.gz 解压2:gzip ...
- 【坚持】Selenium+Python学习记录 DAY9
2018/05/29 [来源:菜鸟教程](http://www.runoob.com/python3/python3-examples.html) 运算符重载 https://segmentfault ...
- 【坚持】Selenium+Python学习之从读懂代码开始 DAY4
2018/05/21 [生成器详解:廖雪峰的官方网站](https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d ...
- 04-matplotlib-柱形图
import numpy as np import matplotlib.pyplot as plt # 柱形图 # 例一 N =5 y = [15,28,10,30,25] index = np.a ...
- Redis集群搭建与使用
前端时间开发中需要用到redis缓存数据,考虑到单台redis的不稳定性,后采用redis集群的方式来实现,由于之前没有接触过,过程中也是踩了不少的坑,拖了三天总算是搞定了,最近公司比较闲,总结了一下 ...
- nodejs 服务器实现区分多客户端请求服务
初始实现 var net = require('net');//1 引入net模块 var chatServer = net.createServer();//创建net服务器 var clientL ...
- iOS中使用RNCryptor对资源文件加密(先加密后拖进项目中)
概述:IPA 在发布时,业务相关的敏感资源文件以明文的形式存储,由于没有加密保护,这些文件在应用发布后 可能被其他人获取,并结合其他漏洞和手段产生真实攻击.所以我们要 1.在设计.开发阶段,集合业务确 ...
- Grunt 5分钟上手:合并+压缩前端代码
Grunt 的各种优点这里就不扯了,对于 新手来说 合并(concat) + 压缩(uglify) 前端代码的需求量应该是最大的,这里以这俩种功能为主做一个5分钟的入门吧! 工作环境 $ node - ...
- (第十周)评论Beta发布
本人所在组:奋斗吧兄弟 按课上展示的顺序对每组进行点评: 1. 飞天小女警 项目:礼物挑选工具 相对于alpha发布时有了很大的进步.项目的界面很漂亮,这个项目的想法很新颖,我很喜欢.礼物的挑选给出 ...