lct+SAM

bzoj4516+bzoj2555

这道题唯一的用处就是教会了我真正的广义SAM

dfs时保留当前节点在后缀自动机中的位置,每个点接着父亲建

lct动态维护right集合大小,用lct维护子树就行了

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. const int N = 1e5 + ;
  6. struct edge {
  7. int nxt, to, w;
  8. } e[N << ];
  9. int n, m, cnt = ;
  10. int h[N], pos[N];
  11. char s[N];
  12. long long sum;
  13. namespace lct
  14. {
  15. struct node {
  16. int ch[];
  17. int f, tag, reg;
  18. } t[N << ];
  19. bool isr(int x) {
  20. return !t[x].f || (t[t[x].f].ch[] != x && t[t[x].f].ch[] != x);
  21. }
  22. int wh(int x) {
  23. return x == t[t[x].f].ch[];
  24. }
  25. void paint(int x, int d) {
  26. t[x].tag += d;
  27. t[x].reg += d;
  28. }
  29. void pushdown(int x) {
  30. if(t[x].tag) {
  31. paint(t[x].ch[], t[x].tag);
  32. paint(t[x].ch[], t[x].tag);
  33. t[x].tag = ;
  34. }
  35. }
  36. void pd(int x) {
  37. if(!isr(x)) {
  38. pd(t[x].f);
  39. }
  40. pushdown(x);
  41. }
  42. void rotate(int x) {
  43. int y = t[x].f, z = t[y].f, w = wh(x);
  44. if(!isr(y)) {
  45. t[z].ch[wh(y)] = x;
  46. }
  47. t[x].f = z;
  48. t[y].ch[w] = t[x].ch[w ^ ];
  49. t[t[x].ch[w ^ ]].f = y;
  50. t[y].f = x;
  51. t[x].ch[w ^ ] = y;
  52. }
  53. void splay(int x) {
  54. pd(x);
  55. for(; !isr(x); rotate(x)) {
  56. if(!isr(t[x].f)) {
  57. rotate(wh(t[x].f) == wh(x) ? t[x].f : x);
  58. }
  59. }
  60. }
  61. void access(int x) {
  62. for(int y = ; x; y = x, x = t[x].f) {
  63. splay(x);
  64. t[x].ch[] = y;
  65. }
  66. }
  67. void link(int u, int v) {
  68. access(u);
  69. splay(u);
  70. access(v);
  71. splay(v);
  72. paint(v, t[u].reg);
  73. t[u].f = v;
  74. }
  75. void cut(int u, int v) {
  76. access(u);
  77. splay(u);
  78. t[u].ch[] = ;
  79. t[v].f = ;
  80. paint(v, -t[u].reg);
  81. }
  82. }
  83. namespace SAM
  84. {
  85. struct node {
  86. int ch[];
  87. int par, val;
  88. } t[N << ];
  89. int root = , sz = ;
  90. int nw(int x) {
  91. t[++sz].val = x;
  92. return sz;
  93. }
  94. int extend(int last, int c) {
  95. int p = last, np = nw(t[p].val + );
  96. lct::t[np].reg = ;
  97. while(p && !t[p].ch[c]) {
  98. t[p].ch[c] = np;
  99. p = t[p].par;
  100. }
  101. if(!p) {
  102. t[np].par = root;
  103. lct::link(np, root);
  104. } else {
  105. int q = t[p].ch[c];
  106. if(t[q].val == t[p].val + ) {
  107. t[np].par = q;
  108. lct::link(np, q);
  109. } else {
  110. int nq = nw(t[p].val + );
  111. lct::link(nq, t[q].par);
  112. lct::cut(q, t[q].par);
  113. lct::link(np, nq);
  114. lct::link(q, nq);
  115. t[nq].par = t[q].par;
  116. t[np].par = t[q].par = nq;
  117. memcpy(t[nq].ch, t[q].ch, sizeof(t[q].ch));
  118. while(p && t[p].ch[c] == q) {
  119. t[p].ch[c] = nq;
  120. p = t[p].par;
  121. }
  122. }
  123. }
  124. sum += t[np].val - t[t[np].par].val;
  125. return np;
  126. }
  127. void solve(char *s) {
  128. int len = strlen(s), now = root;
  129. for(int i = ; i < len; ++i) {
  130. if(!t[now].ch[s[i] - 'a']) {
  131. puts("");
  132. return;
  133. }
  134. now = t[now].ch[s[i] - 'a'];
  135. }
  136. lct::pd(now);
  137. printf("%d\n", lct::t[now].reg);
  138. lct::splay(now);
  139. }
  140. }
  141. void link(int u, int v, int w) {
  142. e[++cnt].nxt = h[u];
  143. h[u] = cnt;
  144. e[cnt].to = v;
  145. e[cnt].w = w;
  146. }
  147. void dfs(int u, int last) {
  148. for(int i = h[u]; i; i = e[i].nxt) {
  149. if(e[i].to == last) {
  150. continue;
  151. }
  152. pos[e[i].to] = SAM::extend(pos[u], e[i].w);
  153. dfs(e[i].to, u);
  154. }
  155. h[u] = ;
  156. }
  157. int main() {
  158. // freopen("1.out", "w", stdout);
  159. int laji;
  160. scanf("%d%d", &laji, &n);
  161. for(int i = ; i < n; ++i) {
  162. int u, v;
  163. scanf("%d%d%s", &u, &v, s);
  164. link(u, v, s[] - 'a');
  165. link(v, u, s[] - 'a');
  166. }
  167. pos[] = ;
  168. dfs(, );
  169. scanf("%d", &m);
  170. while(m--) {
  171. int opt;
  172. scanf("%d", &opt);
  173. if(opt == ) {
  174. printf("%lld\n", sum);
  175. } else if(opt == ) {
  176. int rt, sz;
  177. scanf("%d%d", &rt, &sz);
  178. while(--sz) {
  179. int u, v;
  180. scanf("%d%d%s", &u, &v, s);
  181. link(u, v, s[] - 'a');
  182. link(v, u, s[] - 'a');
  183. }
  184. dfs(rt, );
  185. } else {
  186. scanf("%s", s);
  187. SAM::solve(s);
  188. }
  189. }
  190. return ;
  191. }

bzoj4545的更多相关文章

  1. 【BZOJ4545】DQS的trie 后缀自动机+LCT

    [BZOJ4545]DQS的trie Description DQS的自家阳台上种着一棵颗粒饱满.颜色纯正的trie. DQS的trie非常的奇特,它初始有n0个节点,n0-1条边,每条边上有一个字符 ...

  2. BZOJ4545: DQS的trie

    BZOJ4545: DQS的trie https://lydsy.com/JudgeOnline/problem.php?id=4545 分析: 对trie用dfs建sam复杂度是\(O(n^2)\) ...

  3. BZOJ4545: DQS的trie 广义后缀自动机_LCT

    特别鸣神犇 fcwww 替我调出了无数个错误(没他的话我都快自闭了),祝大佬省选rp++ 板子题,给我写了一天QAQ...... 用 LCT 维护后缀树,暴力更新用 LCT 区间更新链即可 其实,在计 ...

随机推荐

  1. PAT 1057. 数零壹(20)

    给定一串长度不超过105的字符串,本题要求你将其中所有英文字母的序号(字母a-z对应序号1-26,不分大小写)相加,得到整数N,然后再分析一下N的二进制表示中有多少0.多少1.例如给定字符串“PAT ...

  2. ACM-最小生成树之继续畅通project——hdu1879

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/lx417147512/article/details/27092583 ************** ...

  3. eclipse 修改 JDK中的src.zip的路径

    http://blog.sina.com.cn/s/blog_54a1bca7010112fb.html http://www.douban.com/note/211369821/ 1.点 “wind ...

  4. 查询某个字段为null并且某个字段不为null的数据

    查询代码为null且ggid不为null的公司名 select name_of_invested_company from dwtz WHERE code is NULL and ggid is no ...

  5. 更改node版本

    npm install -g n n stable 或 n v4.5.0

  6. 开发rsync启动脚本

    rsync rsync是类unix系统下的数据镜像备份工具——remote sync.一款快速增量备份工具 Remote Sync,远程同步 支持本地复制,或者与其他SSH.rsync主机同步.   ...

  7. <再看TCP/IP第一卷>TCP/IP协议族中的最压轴戏----TCP协议及细节

    题外话:刚刚过去的半个月实在是忙得我喘不过来气,虽然手里还压着几个项目得在期末考试之前做完,但是想想还是更新一下随笔,稍微换个心情.另外小吐槽一下那些在博客园里原封不动抄书当随笔的人,唉真是....算 ...

  8. Luogu-2657 [SCOI2009]windy数

    很少做数位\(dp\)的题,做道题学习一下吧. 记忆化搜索,\(f[10][10][2][2]\)分别记录当前位置,上一位数,是否有前导零和是否有大小上限. 题目要满足相邻两个数相差不小于2,如果有前 ...

  9. MSSQL遇到以零作除数错误的处理方法

    在sql server中做除法处理的时候,我们经常需要处理除数为零的情况,因为如果遇到这种情况的时候,sqlserver会抛出遇到以零作除数错误的异常,我们总不希望把这个异常显示给用户吧. 做个会报这 ...

  10. Oracle的PL_SQL的异常处理

    --什么是异常 --异常是在PL/SQL运行过程中有可能出现的错误. --执行异常的语句 exception when [异常] when --异常输出信息. --Oracle的预定义异常 CASE_ ...