BZOJ4545: DQS的trie 广义后缀自动机_LCT
特别鸣神犇 fcwww 替我调出了无数个错误(没他的话我都快自闭了),祝大佬省选rp++
板子题,给我写了一天QAQ......
用 LCT 维护后缀树,暴力更新用 LCT 区间更新链即可
其实,在计算本职不同子串的时候很多网友算的都有点麻烦
不管实在后缀自动机,还是广义后缀自动机中,动态更新本质不同子串数量用最后新加的点更新即可,和其他点是无关的.
Code:
#include <queue>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout)
#define maxn 800000
#define N 10
#define ll long long
using namespace std;
char str[maxn];
long long cur_ans;
struct Link_Cut_Tree{
int ch[maxn][2],f[maxn],tag[maxn],sta[maxn],val[maxn];
int get(int x) {return ch[f[x]][1]==x; }
int which(int x){ return ch[f[x]][1]==x;}
int isRoot(int x){ return !(ch[f[x]][1]==x||ch[f[x]][0]==x);}
int lson(int x){ return ch[x][0];}
int rson(int x){return ch[x][1];}
void add(int x,int delta){if(!x)return;val[x]+=delta,tag[x]+=delta;}
void pushdown(int x){if(tag[x]) add(lson(x),tag[x]),add(rson(x),tag[x]),tag[x]=0;}
void rotate(int x){
int old=f[x],fold=f[old],which=get(x);
if(!isRoot(old)) ch[fold][ch[fold][1]==old]=x;
ch[old][which]=ch[x][which^1],f[ch[old][which]]=old;
ch[x][which^1]=old,f[old]=x,f[x]=fold;
}
void splay(int x){
int v=0,u=x;
sta[++v]=u;
while(!isRoot(u)) sta[++v]=f[u],u=f[u];
while(v) pushdown(sta[v--]);
u=f[u];
for(int fa;(fa=f[x])!=u && x;rotate(x))
if(f[fa]!=u) rotate(get(fa)==get(x)?fa:x);
}
void Access(int x){
for(int y=0;x;y=x,x=f[x])
splay(x),ch[x][1]=y;
}
void link(int a,int b){
Access(a),splay(a),add(a,val[b]),f[b]=a;
}
void cut(int b){
Access(b),splay(b);
add(lson(b),-val[b]),f[lson(b)]=ch[b][0]=0;
}
}tree;
struct SAM{
int ch[maxn][10],f[maxn],dis[maxn];
int tot,last;
void init(){ last=tot=1; }
int ins(int c){
int p=last,np=++tot; last=np; dis[np]=dis[p]+1;tree.val[np]=tree.tag[np]=1;
while(p&&!ch[p][c])ch[p][c]=np,p=f[p];
if(!p) f[np]=1,tree.link(1,np);
else{
int q=ch[p][c],nq;
if(dis[q]==dis[p]+1)f[np]=q,tree.link(q,np);
else{
nq=++tot;
dis[nq]=dis[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
f[nq]=f[q];
tree.link(f[q],nq),tree.cut(q),tree.link(nq,q),tree.link(nq,np);
f[q]=f[np]=nq;
while(p&&ch[p][c]==q) ch[p][c]=nq,p=f[p];
}
}
cur_ans+=dis[np] - dis[f[np]];
return np;
}
}sam;
struct Node{
int u,c;
Node(int u=0,int c=0):u(u),c(c){}
};
queue<int>Q;
vector<int>mark;
vector<Node>G[maxn];
int idx[maxn];
void DFS(int u,int fa){
int k=G[u].size();
for(int i=0;i<k;++i){
Node j=G[u][i];
if(j.u==fa) continue;
sam.last=idx[u],idx[j.u]=sam.ins(j.c);
DFS(j.u,u);
}
G[u].clear();
}
void build_Tree(int n,int st){
for(int i=1;i<n;++i) {
int u,v;
char c[10];
scanf("%d%d",&u,&v);
scanf("%s",c);
G[u].push_back(Node(v,c[0]-'a'));
G[v].push_back(Node(u,c[0]-'a'));
}
DFS(st,0);
}
int main(){
//setIO("input");
int lll,n,m;
scanf("%d",&lll); sam.init(),idx[1] = 1; scanf("%d",&n);
build_Tree(n,1); scanf("%d",&m); for(int i=1;i<=m;++i) {
int opt_idx,a,b;
scanf("%d",&opt_idx);
if(opt_idx==1) printf("%lld\n",cur_ans);
if(opt_idx==2) {
scanf("%d%d",&a,&b);
build_Tree(b,a);
}
if(opt_idx==3) {
scanf("%s",str);
a=strlen(str);
b=1;
bool flag = 0;
for(int j=0;j<a;++j) {
b=sam.ch[b][str[j]-'a'];
if(!b) flag = 1;
}
if(flag) printf("0\n");
else {
tree.Access(b);
tree.splay(b);
printf("%d\n",tree.val[b]);
}
}
}
return 0;
}
BZOJ4545: DQS的trie 广义后缀自动机_LCT的更多相关文章
- bzoj3926/luoguP3346 [Zjoi2015]诸神眷顾的幻想乡(trie上构建广义后缀自动机)
bzoj3926/luoguP3346 [Zjoi2015]诸神眷顾的幻想乡(trie上构建广义后缀自动机) bzoj Luogu 题解时间 给你个无根trie树(你管这叫trie树?),问你选取一条 ...
- bzoj3926: [Zjoi2015]诸神眷顾的幻想乡 对[广义后缀自动机]的一些理解
先说一下对后缀自动机的理解,主要是对构造过程的理解. 构造中,我们已经得到了前L个字符的后缀自动机,现在我们要得到L+1个字符的后缀自动机,什么需要改变呢? 首先,子串$[0,L+1)$对应的状态不存 ...
- BZOJ 3473: 字符串 [广义后缀自动机]
3473: 字符串 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 354 Solved: 160[Submit][Status][Discuss] ...
- BZOJ.3926.[ZJOI2015]诸神眷顾的幻想乡(广义后缀自动机)
题目链接 要对多个串同时建立SAM,有两种方法: 1.将所有串拼起来,中间用分隔符隔开,插入字符正常插入即可. 2.在这些串的Trie上建SAM.实际上并不需要建Trie,还是只需要正常插入(因为本来 ...
- 【codeforces666E】Forensic Examination 广义后缀自动机+树上倍增+线段树合并
题目描述 给出 $S$ 串和 $m$ 个 $T_i$ 串,$q$ 次询问,每次询问给出 $l$ .$r$ .$x$ .$y$ ,求 $S_{x...y}$ 在 $T_l,T_{l+1},...,T_r ...
- bzoj 3277 串 && bzoj 3473 字符串 && bzoj 2780 [Spoj]8093 Sevenk Love Oimaster——广义后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3277 https://www.lydsy.com/JudgeOnline/problem.p ...
- 【bzoj5084】hashit 广义后缀自动机+树链的并+STL-set
题目描述 你有一个字符串S,一开始为空串,要求支持两种操作 在S后面加入字母C 删除S最后一个字母 问每次操作后S有多少个两两不同的连续子串 输入 一行一个字符串Q,表示对S的操作 如果第i个字母是小 ...
- BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机 后缀自动机 字符串
https://www.lydsy.com/JudgeOnline/problem.php?id=3926 广义后缀自动机是一种可以处理好多字符串的一种数据结构(不像后缀自动机只有处理一到两种的时候比 ...
- BZOJ3277 串 【广义后缀自动机】
Description 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中 至少k个字符串的子串(注意包括本身). Input 第一行两个整数n, ...
随机推荐
- WEBGL学习【十二】鼠标操作场景
<!DOCTYPE HTML> <html lang="en"> <head> <title>Listing 7-3 and 7-4 ...
- nyoj314-斐波那契数列四吧
斐波那契数列四吧 时间限制:3000 ms | 内存限制:65535 KB 难度:2 描述 斐波那契数列为:0,1,1,2,3,5,8,13....,常规递推公式为f(n)=f(n-1)+f(n- ...
- fun(int **p)的使用
#include <iostream>using namespace std;void fun(int **p){ cout << p[0][0] << endl; ...
- Servlet 3.1 标准(一)
概述 什么是Servlet Servlet 是一个基于Java 的Web组件,由容器管理生成的动态内容.就像其他的Java组件一样,Servlet是平台无关的Java类所编译成的字节码,可以被动态加载 ...
- Mybatis拦截器执行过程解析
上一篇文章 Mybatis拦截器之数据加密解密 介绍了 Mybatis 拦截器的简单使用,这篇文章将透彻的分析 Mybatis 是怎样发现拦截器以及调用拦截器的 intercept 方法的 小伙伴先按 ...
- OA项目知识总结
struts文件配置 --------------------------------------------------------- 配置c3po链接池 --------------------- ...
- C#中的LINQ 基础
1.LINQ的数据源 必须可枚举的,即必须是数组或者集合 (继承了IEnumerable<T>接口就可以,注意是IEnumerable<T>,不是IEnumerable接口,不 ...
- Mybatis分页插件2.0版本号公布
项目地址:http://git.oschina.net/free/Mybatis_PageHelper 软件介绍:http://www.oschina.net/p/mybatis_pagehelper ...
- 一个关于Class的小点
public 是公有 private 是私有 没有写就是private
- HDU 5078 Revenge of LIS II(dp LIS)
Problem Description In computer science, the longest increasing subsequence problem is to find a sub ...