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的更多相关文章

  1. 【BZOJ2555】SubString(后缀自动机,Link-Cut Tree)

    [BZOJ2555]SubString(后缀自动机,Link-Cut Tree) 题面 BZOJ 题解 这题看起来不难 每次要求的就是\(right/endpos\)集合的大小 所以搞一个\(LCT\ ...

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

    [BZOJ2555]SubString Description 懒得写背景了,给你一个字符串init,要求你支持两个操作         (1):在当前字符串的后面插入一个字符串         (2 ...

  3. 【BZOJ-2555】SubString 后缀自动机 + LinkCutTree

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

  4. 【BZOJ2555】SubString

    算是学会sam了吧…… 原题: 懒得写背景了,给你一个字符串init,要求你支持两个操作        (1):在当前字符串的后面插入一个字符串        (2):询问字符串s在当前字符串中出现了 ...

  5. 【BZOJ2555】SubString(后缀自动机,LCT)

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

  6. 【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 ...

  7. 【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 ...

  8. 【LeetCode】哈希表 hash_table(共88题)

    [1]Two Sum (2018年11月9日,k-sum专题,算法群衍生题) 给了一个数组 nums, 和一个 target 数字,要求返回一个下标的 pair, 使得这两个元素相加等于 target ...

  9. 【LeetCode】字符串 string(共112题)

    [3]Longest Substring Without Repeating Characters (2019年1月22日,复习) [5]Longest Palindromic Substring ( ...

随机推荐

  1. VSCode配合ESLint自动修复格式化

    开发Vue或者React的项目的时候,我们经常用到ESLint进行代码的校验,当代码出现不符合规范的格式的时候,ESLint会在控制台提示相关的异常信息. ESLint极大的提高了团队代码的一致性和规 ...

  2. Daily Scrum2 11.4

    昨天的任务大家都已经完成,daily scrum记录的是当日已经完成的任务. 今日任务列表: 杨伊:完成团队作业之软件测评的功能部分 徐钧鸿:CodingCook的model和helper部分 张艺: ...

  3. 团队计划backlog---DayTwo

    任务索引卡(Two): 1.  季方:实现界面跳转,数据库相关数据的显示 的测试: 2.  司宇航:添加部分团队博客,并测试: 3.  王金萱.马佳慧:学习爬虫的相关内容,为将来统计博客部分做准备: ...

  4. Chapter 1 概述

    软件分为通用软件和应用软件,具有复杂.不可见和不断变化的特点:从出现到现在共经历了四个重要的发展阶段,但现在的软件发展依然存在着许多问题. 软件工程是采用工程的概念.原理.技术和方法来开发与维护软件, ...

  5. POJ 1185 炮兵阵地 状压dp

    题目链接: http://poj.org/problem?id=1185 炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K 问题描述 司令部的将军们打算在N*M ...

  6. Android开发--第一个活动

    一.创建工程   1 项目名:MyActivity 包名:com.iflytek.myactivity 2 为了便于学习,不勾选Create Activity.然后finish,工程创建完成 END ...

  7. git的使用(本地及关联远程,上传到远程)

    前言:本想这个博客就是用来交作业的,因为作业,学习了git ,现在觉得,既然有这个博客了,就好好用一下吧,也给自己养成个好习惯,就也来记录一下吧,关于git的本地仓库上传,本地与远程的关联,从本地上传 ...

  8. Java面试&编写程序:使子线程循环10次,紧接着主线程循环100次,来回50次

    package com.cwcec.test; public class TraditionalThreadCommunication { /** * @param args */ public st ...

  9. Android之自定义View学习(一)

    Android之自定义View学习(一) Canvas常用方法: 图片来源 /** * Created by SiberiaDante on 2017/6/3. */ public class Bas ...

  10. Git查看与修改用户名、邮箱(转载)

    用户名和邮箱的作用: 用户名和邮箱地址相当于你的身份标识,是本地Git客户端的一个变量,不会随着Git库而改变. 每次commit都会用用户名和邮箱纪录. github的contributions跟你 ...