Description

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

毒瘤

显然就是sam求endpos大小,强套LCT。
时隔多年又打了一次维护子树大小。
大致就是维护:
fsum[x]表示虚父亲为x的tsum和。
tsum[x]表示x的splay和,=tsum[child] + fsum[x] + v[x]

总共有几个细节需要注意

  1. access时相当于实化一条虚边,添加一条虚边。要修改贡献,不必考虑对更上方的影响因为会access到。
  2. link时要添加虚边,此时假若是从fa[a]=b,则需要对b修改贡献。将b access并splay,就不用考虑对上方的贡献了。
  3. cut时也要相应的减去贡献。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;int QQ,mask,le;
const int N = 6e5 + 10, E = 4e6 + 10;
char s[E],type[10];void decode(int mask) {//  cout<<"SDFSADF"<<mask<<endl;for (int i = 0; i < le; i++) {mask = (mask * 131 + i) % le;swap(s[i],s[mask]);}
}int fail[N * 2],c[N * 2][26],tot,last,v[N * 2],len[N * 2];
int fa[N * 2], fsum[N * 2], rev[N * 2], ch[N * 2][2], tsum[N * 2];
//fsum 自己虚子树大小,tsum splay子树虚子树大小 + v, v 自己权值 void update(int x) {tsum[x] = tsum[ch[x][0]] + tsum[ch[x][1]] + fsum[x] + v[x];
}void reverse(int x) {if (!x) return;rev[x] ^= 1;swap(ch[x][0],ch[x][1]);
}void down(int x) {if (rev[x]) {reverse(ch[x][0]);reverse(ch[x][1]);rev[x] = 0;}
}#define gc(x) ((ch[fa[x]][1] == (x)))
#define isroot(x) ((ch[fa[x]][0] != (x)) && (ch[fa[x]][1] != (x)))void rotate(int x) {int y = fa[x], z = gc(x);ch[y][z] = ch[x][1-z];if (ch[x][1-z]) fa[ch[x][1-z]] = y;fa[x] = fa[y];if (!isroot(y)) ch[fa[y]][gc(y)] = x;fa[y] = x;ch[x][1-z] = y;update(y);
}int Q[N * 2];
void splay(int x) {int t = x;while (!isroot(t)) Q[++Q[0]] = t, t = fa[t];Q[++Q[0]] = t;while (Q[0]) down(Q[Q[0]--]);while (!isroot(x)) {int y = fa[x];if (!isroot(y))if (gc(x) == gc(y)) rotate(y);elserotate(x);rotate(x);}update(x);
}void access(int x) {for (int i = 0; x; i = x, x = fa[x]) {splay(x);fsum[x] -= tsum[i];fsum[x] += tsum[ch[x][1]];ch[x][1] = i;update(x);}
}void makeroot(int x) {access(x);splay(x);reverse(x);
}void link(int a, int b) {//  printf("link %d %d\n",a,b);makeroot(a);access(a);splay(a);fa[a] = b;access(b);splay(b);fsum[b] += tsum[a];update(b);
}void cut(int a, int b) {//  printf("cut %d %d\n",a,b);makeroot(a);access(b);splay(a);ch[a][1] = 0, fa[b] = 0;tsum[a] -= tsum[b];
}void insert(char r) {r-='A';int cur = ++tot; tsum[cur] = v[cur] = 1;len[cur] = len[last] + 1;for (; last && c[last][r] == 0; last = fail[last]) c[last][r] = cur;if (last) {int p = c[last][r];if (len[p] == len[last] + 1) link(cur,p), fail[cur] = p;else {int nep = ++tot;memcpy(c[nep],c[p],sizeof c[p]);fail[nep] = fail[p];cut(p, fail[p]);link(nep,fail[p]);link(nep, p);link(nep, cur);fail[p] = fail[cur] = nep;len[nep] = len[last] + 1;for (; c[last][r] == p; last = fail[last])c[last][r] = nep;}} else {link(cur,1), fail[cur] = 1;}last = cur;
}int main() {//freopen("a.in","r",stdin);cin>>QQ;scanf("%s",s);le = strlen(s);tot = last = 1;for (int i = 0; i < le; i++) insert(s[i]);for (int ww = 1; ww <= QQ; ww++) {scanf("%s %s\n",type,s);le = strlen(s);decode(mask);if (type[0] == 'Q') {int now = 1, got = 0;for (int i =0; i < le; i++) {now = c[now][s[i]-'A'];if (now == 0) {got = 1;printf("0\n"); break;}}if (got) continue;makeroot(1);access(now);mask ^= fsum[now] + v[now];printf("%d\n",fsum[now] + v[now]);} else {for (int i = 0; i < le; i++)insert(s[i]);}}
}

bzoj2555 SubString (SAM+LCT维护子树大小/ETT)相关推荐

  1. 【uoj#207】共价大爷游长沙 随机化+LCT维护子树信息

    题目描述 给出一棵树和一个点对集合S,多次改变这棵树的形态.在集合中加入或删除点对,或询问集合内的每组点对之间的路径是否都经过某条给定边. 输入 输入的第一行包含一个整数 id,表示测试数据编号,如第 ...

  2. bzoj 4530 [Bjoi2014]大融合——LCT维护子树信息

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4530 LCT维护子树 siz .设 sm[ ] 表示轻儿子的 siz 和+1(1是自己的si ...

  3. SubString SAM+LCT

    P5212 SubString 题意 给出字符串S和操作次数Q ADD:往S后继续加一个字符串 QUERY:求给出的字符串在S中出现次数 考虑SAM,插入是O(n)的,查询位置时O(n)的,问题是怎么 ...

  4. LCT维护子树信息(BZOJ4530:[BJOI2014]大融合)

    题面 没有权限号的可以去LOJ Sol 大家都知道,\(LCT\)上有许多实边和虚边 实边就是每棵\(Splay\)上的既认父亲又认儿子的边 虚边就是\(Splay\)和\(Splay\)之间只认父亲 ...

  5. BZOJ 4530 大融合 LCT维护子树信息

    题意: N<=1e5个点,Q<=1e5个操作. 支持加一条边(u,v)(保证图是森林).询问经过边(u,v)的简单路径条数(保证(u,v)存在). 分析: 数据结构学傻了的我,表示并不会用 ...

  6. BZOJ 3639: Query on a tree VII LCT_set维护子树信息

    用 set 维护子树信息,细节较多. Code: #include <cstring> #include <cstdio> #include <algorithm> ...

  7. 一类用 LCT 维护信息的题目

    1 给定一棵n个点的树,点有正点权,支持修改点权,查询带权直径. 普通的 DP 需要维护最长链和次长链,带修改的话不容易动态维护.因此我们采用另一种方法:找两次最远点. LCT 维护的是:对于一棵 s ...

  8. LOJ 121 「离线可过」动态图连通性——LCT维护删除时间最大生成树 / 线段树分治...

    题目:https://loj.ac/problem/121 离线,LCT维护删除时间最大生成树即可.注意没有被删的边的删除时间是 m+1 . 回收删掉的边的节点的话,空间就可以只开 n*2 了. #i ...

  9. bzoj 4736: 温暖会指引我们前行 (LCT 维护最大生成树)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4736 题面: 寒冬又一次肆虐了北国大地 无情的北风穿透了人们御寒的衣物 可怜虫们在冬夜中发出 ...

  10. P4172 [WC2006]水管局长 LCT维护最小生成树

    \(\color{#0066ff}{ 题目描述 }\) SC 省 MY 市有着庞大的地下水管网络,嘟嘟是 MY 市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的 ...

最新文章

  1. 青海省西宁市职称计算机考试试题,【青海西宁2017年第一批职称计算机考试时间4月8日起】- 环球网校...
  2. Spring5源码 - 构建源码环境
  3. 扩展中国剩余定理(模板)
  4. jdbc连接oracle的几种格式
  5. JVM 的三色标记算法详解
  6. linux sort命令 性能,Linux sort 命令简单使用
  7. GridView控件常见问题及处理方法
  8. selenium web的自动化测试工具
  9. Mac电脑显示器颜色不正该如何调整?
  10. 用户密码MD5和SHA加密
  11. GoLang之iface 和 eface 的区别是什么(3)
  12. 【原创】驳罗素《我为什么不是基督徒》
  13. 知识图谱及其关键技术
  14. 如何帮助新员工快速融入团队?先搞清楚“融入”背后的难点,再对症下药
  15. web前端网页美化重器-------css
  16. Python与单片机通信——serial库
  17. 无损数据动态磁盘逆转为基本磁盘的方法
  18. 9个好用的搜索小技巧
  19. 博客园博客怎样让百度收录?
  20. 工行nc银企互联java代码_C#工行 银企互联demo(NC)

热门文章

  1. c语言设计无纸化考试系统多少钱,无纸化考试系统解决方案
  2. 常见windows进程说明
  3. Android7.0(Android N)适配教程,心得
  4. 【计算机组成原理】中央处理器总结——基本知识要点汇总
  5. pyecharts 旋转折线图的X轴标签
  6. 内热外寒感冒,不能乱吃药
  7. 共享IPFS生态红利丨IPFS合伙人招募大会哈尔滨站圆满落幕
  8. ios13 微信提示音插件_ios13微信提示音如何进行更改
  9. 【Unity】关于GPU异步回读Android兼容性问题
  10. Oracle event px,oracle wait event:PX Deq Credit: send blkd