2555: SubString

链接

题意:

  动态在末尾加入一个字符串,询问一个字符串出现了多少次。

分析:

  如果没有动态加入,那么建出SAM后,求出parent树上,每个点|Right|,然后走一遍找到对应的点,这个点的Right集合的大小就是答案。

  求Right可以从叶子结点往上走一遍。

  考虑动态加入,那么会在parent树上,增加一点,并且支持加边删边,求一个点的权值,在一条到根的链上增加一个数,所以LCT维护parent树。

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ; struct LCT{
int fa[N], ch[N][], sk[N], top, tag[N], R[N];
inline void add(int x,int v) {
if (x) R[x] += v, tag[x] += v;
}
inline void pushdown(int x) {
if (tag[x]) add(ch[x][], tag[x]), add(ch[x][], tag[x]), tag[x] = ;
}
inline bool isroot(int x) {
return ch[fa[x]][] != x && ch[fa[x]][] != x;
}
inline int son(int x) {
return ch[fa[x]][] == x;
}
inline void rotate(int x) {
int y = fa[x], z = fa[y], c = son(y), b = son(x), a = ch[x][!b];
if (!isroot(y)) ch[z][c] = x; fa[x] = z;
ch[x][!b] = y; fa[y] = x;
ch[y][b] = a; if (a) fa[a] = y;
}
inline void splay(int x) {
top = , sk[] = x;
for (int i = x; !isroot(i); i = fa[i]) sk[++top] = fa[i];
while (top) pushdown(sk[top --]);
while (!isroot(x)) {
int y = fa[x];
if (isroot(y)) rotate(x);
else {
if (son(x) == son(y)) rotate(y), rotate(x);
else rotate(x), rotate(x);
}
}
}
inline void access(int x) {
for (int last = ; x; last = x, x = fa[x]) {
splay(x); ch[x][] = last;
}
}
inline void link(int x,int y) { // 这是一棵有根树,每条边的方向确定(指向父节点),不需要makeroot,后面是取出这条链,打标记
fa[x] = y; access(y); splay(y); add(y, R[x]);
}
inline void cut(int x) { // x 和 fa[x] 断开,fa[x]的深度小,所以是x的左儿子
access(x); splay(x); add(ch[x][], -R[x]);
fa[ch[x][]] = ; ch[x][] = ;
}
}lct; int ch[N][], len[N], fa[N], Last = , Index = ;
void extend(int c) {
int np = ++Index, p = Last; lct.R[np] = ;
for (; p && !ch[p][c]; p = fa[p]) ch[p][c] = np;
if (!p) fa[np] = , lct.link(np, );
else {
int Q = ch[p][c];
if (len[Q] == len[p] + ) fa[np] = Q, lct.link(np, Q);
else {
int NQ = ++Index;
fa[NQ] = fa[Q]; lct.link(NQ, fa[Q]);
len[NQ] = len[p] + ;
memcpy(ch[NQ], ch[Q], sizeof ch[Q]);
fa[Q] = fa[np] = NQ;
lct.cut(Q); lct.link(Q, NQ); lct.link(np, NQ);
for (; p && ch[p][c] == Q; p = fa[p]) ch[p][c] = NQ;
}
}
Last = np;
}
void build(char *s,int len) {
for (int i = ; i < len; ++i) extend(s[i] - 'A');
}
int find(char *s,int len) {
int now = ;
for (int i = ; i < len; ++i) {
now = ch[now][s[i] - 'A'];
if (!now) return ;
}
lct.splay(now);
return lct.R[now];
}
void getstr(char *s,int x,int len) {
for (int i = ; i < len; ++i) {
x = (x * + i) % len;
swap(s[i], s[x]);
}
}
char s[N], opt[];
int main() {
int n = read(), L, lastans = , ans;
scanf("%s", s);
L = strlen(s);
build(s, L);
for (int i = ; i <= n; ++i) {
scanf("%s%s", opt, s);
L = strlen(s);
getstr(s, lastans, L);
if (opt[] == 'Q') {
ans = find(s, L); lastans ^= ans;
printf("%d\n", ans);
}
else build(s, L);
}
return ;
}

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. 2555: SubString[LCT+SAM]

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

  4. 【BZOJ 2555】 2555: SubString (SAM+LCT)

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

  5. bzoj 2555 SubString(SAM+LCT)

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

  6. ●BZOJ 2555 SubString

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

  7. 【BZOJ】2555: SubString(后缀自动机)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2555 学到了如何快速维护right值orz (不过这仍然是暴力维护,可以卡到O(n) 首先我们在加一 ...

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

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

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

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

随机推荐

  1. 卸载oracle 10g

    1.开始->设置->控制面板->管理工具->服务——>   停止所有Oracle服务.(没有起动的就不用停用了)2.开始->程序->Oracle - OraD ...

  2. 【Excel】如何用SUMIF实现SUMIFS的功能

    如何用SUMIF实现SUMIFS的功能   添加辅助列,辅助列内容为"条件区域1内容+条件区域内容2" 举个例子,我要挑选出"二车间"的"过桥过路费& ...

  3. SOJ 4580 动态规划之01背包 (01背包)

    Description Sidney想去Gandtom家玩.但Sidney家和Gandtom家之间是高低不平.坑坑洼洼的土路.所以他需要用他的背包装几袋稀的泥,在路上铺平一些干的土,使路变成平整的泥土 ...

  4. c# 匿名函数与托付

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/han_yankun2009/article/details/26290779    在 2.0之前的 ...

  5. 20165318 2017-2018-2 《Java程序设计》第七周学习总结

    20165318 2017-2018-2 <Java程序设计>第七周学习总结 目录 学习过程遇到的问题及总结 教材学习内容总结 第11章 JDBC与MySQL数据库 错题总结 第五周错题总 ...

  6. 如何使用正则做文本数据的清洗(附免费AI视频福利)

    手工打造文本数据清洗工具 作者 白宁超 2019年4月30日09:43:59 前言:数据清理指删除.更正错误.不完整.格式有误或多余的数据.数据清理不仅仅更正错误,同样加强来自各个单独信息系统不同数据 ...

  7. Sublime Text 自动生成文件头部注释(版权信息):FileHeader 插件的使用

    (一)安装步骤 1.先安装一个 Package Control 插件.相信大家使用 Sublime 的话都有安装这个了2.Preference -> Package Control -> ...

  8. 使用vue.js实现checkbox的全选和多个的删除功能

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...

  9. PAT乙级1021

    1021 个位数统计 (15 分)   给定一个 k 位整数 N=d​k−1​​10​k−1​​+⋯+d​1​​10​1​​+d​0​​ (0≤d​i​​≤9, i=0,⋯,k−1, d​k−1​​& ...

  10. C语言程序设计I—第六周教学

    第六周教学总结(8/10-14/10) 教学内容 第二章 用C语言编写程序 2.4 输出华氏-摄氏温度转换表 课前准备 在蓝墨云班课发布资源: PTA:2018秋第六周作业 分享码:88C28D89E ...