lct+SAM

bzoj4516+bzoj2555

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

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

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

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + ;
struct edge {
int nxt, to, w;
} e[N << ];
int n, m, cnt = ;
int h[N], pos[N];
char s[N];
long long sum;
namespace lct
{
struct node {
int ch[];
int f, tag, reg;
} t[N << ];
bool isr(int x) {
return !t[x].f || (t[t[x].f].ch[] != x && t[t[x].f].ch[] != x);
}
int wh(int x) {
return x == t[t[x].f].ch[];
}
void paint(int x, int d) {
t[x].tag += d;
t[x].reg += d;
}
void pushdown(int x) {
if(t[x].tag) {
paint(t[x].ch[], t[x].tag);
paint(t[x].ch[], t[x].tag);
t[x].tag = ;
}
}
void pd(int x) {
if(!isr(x)) {
pd(t[x].f);
}
pushdown(x);
}
void rotate(int x) {
int y = t[x].f, z = t[y].f, w = wh(x);
if(!isr(y)) {
t[z].ch[wh(y)] = x;
}
t[x].f = z;
t[y].ch[w] = t[x].ch[w ^ ];
t[t[x].ch[w ^ ]].f = y;
t[y].f = x;
t[x].ch[w ^ ] = y;
}
void splay(int x) {
pd(x);
for(; !isr(x); rotate(x)) {
if(!isr(t[x].f)) {
rotate(wh(t[x].f) == wh(x) ? t[x].f : x);
}
}
}
void access(int x) {
for(int y = ; x; y = x, x = t[x].f) {
splay(x);
t[x].ch[] = y;
}
}
void link(int u, int v) {
access(u);
splay(u);
access(v);
splay(v);
paint(v, t[u].reg);
t[u].f = v;
}
void cut(int u, int v) {
access(u);
splay(u);
t[u].ch[] = ;
t[v].f = ;
paint(v, -t[u].reg);
}
}
namespace SAM
{
struct node {
int ch[];
int par, val;
} t[N << ];
int root = , sz = ;
int nw(int x) {
t[++sz].val = x;
return sz;
}
int extend(int last, int c) {
int p = last, np = nw(t[p].val + );
lct::t[np].reg = ;
while(p && !t[p].ch[c]) {
t[p].ch[c] = np;
p = t[p].par;
}
if(!p) {
t[np].par = root;
lct::link(np, root);
} else {
int q = t[p].ch[c];
if(t[q].val == t[p].val + ) {
t[np].par = q;
lct::link(np, q);
} else {
int nq = nw(t[p].val + );
lct::link(nq, t[q].par);
lct::cut(q, t[q].par);
lct::link(np, nq);
lct::link(q, nq);
t[nq].par = t[q].par;
t[np].par = t[q].par = nq;
memcpy(t[nq].ch, t[q].ch, sizeof(t[q].ch));
while(p && t[p].ch[c] == q) {
t[p].ch[c] = nq;
p = t[p].par;
}
}
}
sum += t[np].val - t[t[np].par].val;
return np;
}
void solve(char *s) {
int len = strlen(s), now = root;
for(int i = ; i < len; ++i) {
if(!t[now].ch[s[i] - 'a']) {
puts("");
return;
}
now = t[now].ch[s[i] - 'a'];
}
lct::pd(now);
printf("%d\n", lct::t[now].reg);
lct::splay(now);
}
}
void link(int u, int v, int w) {
e[++cnt].nxt = h[u];
h[u] = cnt;
e[cnt].to = v;
e[cnt].w = w;
}
void dfs(int u, int last) {
for(int i = h[u]; i; i = e[i].nxt) {
if(e[i].to == last) {
continue;
}
pos[e[i].to] = SAM::extend(pos[u], e[i].w);
dfs(e[i].to, u);
}
h[u] = ;
}
int main() {
// freopen("1.out", "w", stdout);
int laji;
scanf("%d%d", &laji, &n);
for(int i = ; i < n; ++i) {
int u, v;
scanf("%d%d%s", &u, &v, s);
link(u, v, s[] - 'a');
link(v, u, s[] - 'a');
}
pos[] = ;
dfs(, );
scanf("%d", &m);
while(m--) {
int opt;
scanf("%d", &opt);
if(opt == ) {
printf("%lld\n", sum);
} else if(opt == ) {
int rt, sz;
scanf("%d%d", &rt, &sz);
while(--sz) {
int u, v;
scanf("%d%d%s", &u, &v, s);
link(u, v, s[] - 'a');
link(v, u, s[] - 'a');
}
dfs(rt, );
} else {
scanf("%s", s);
SAM::solve(s);
}
}
return ;
}

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. Django 动态导入配置文件的类

    导入配置文件的类 #如何用字符串的形式动态导入模块 from importlib import import_module path=''api.cors.CORSMiddleware' #CORSM ...

  2. PAT 1061. 判断题(15)

    判断题的评判很简单,本题就要求你写个简单的程序帮助老师判题并统计学生们判断题的得分. 输入格式: 输入在第一行给出两个不超过100的正整数N和M,分别是学生人数和判断题数量.第二行给出M个不超过5的正 ...

  3. easyui的 一些经验

    1. 渲染网络表格时,行操作 <th field="sort_num" width="10" data-options="field:'id', ...

  4. [Java面试一]Spring总结以及在面试中的一些问题.(转发:http://www.cnblogs.com/wang-meng/p/5701982.html)

    1.谈谈你对spring IOC和DI的理解,它们有什么区别? IoC Inverse of Control 反转控制的概念,就是将原本在程序中手动创建UserService对象的控制权,交由Spri ...

  5. awk substr()函数

    awk 里的substr函数用法举例: 要截取要截取的内容1: F115!16201!1174113017250745 10.86.96.41 211.140.16.1 200703180718F12 ...

  6. iOS 图文混排 链接 可点击

    对于这个话题 我想到 1 第一个解决方法就是使用 webView 比较经典 把所有复杂工作都交给控件本身去处理了,  但是好像好多需要自定义的地方 没法从 webView获得响应回调 :(估计也可以实 ...

  7. python调用java jython

    环境:openjdk8,python2.7,jython2.7jython下载地址     http://www.jython.org/downloads.html 下载完成后,运行下面命令 java ...

  8. Vue组件通信(传值)

    先介绍一下什么是组件把: 创建组件的两种方式: 全局组件 // 组件就是vue的一个拓展实例 let component=Vue.extend({ data(){ return{ //与vue实例中的 ...

  9. 针对PHP性能方面编程技巧的总结

    注:本文为作者多年工作经验总结,转贴请注明出处 Albert Wang 做PHP已经有4年多了吧,总是没写点什么总结一下,现在开始写博客了,也顺便总结下吧,留给那些新入行的朋友看看. 1. 不宜频繁使 ...

  10. Windows下控制Nginx的状态

    Windows下Nginx的启动.停止等命令 在Windows下使用Nginx,我们需要掌握一些基本的操作命令,比如:启动.停止Nginx服务,重新载入Nginx等,下面我就进行一些简单的介绍.1.启 ...