[Jsoi2015]字符串树
https://www.zybuluo.com/ysner/note/1298148
题面
字符串树本质上还是一棵树,即\(N\)个节点\(N-1\)条边的连通无向无环图,节点
从\(1\)到\(N\)编号。与普通的树不同的是,树上的每条边都对应了一个字符串。萌萌
和\(JYY\)在树下玩的时候,萌萌决定考一考\(JYY\)。每次萌萌都写出一个字符串\(S\)和
两个节点\(U,V\),需要\(JYY\)立即回答\(U\)和\(V\)之间的最短路径(即之间边数最少的
路径。由于给定的是一棵树,这样的路径是唯一的)上有多少个字符串以为前
缀。
- \(n,Q\leq10^5\)
解析
维护树上距离,我能想到的也只有树链剖分了。
树链剖分维护树上距离,实际上是通过每个点到根节点的距离来进行的。
那么这题也一样。
维护一下每个点到根节点的字符串。
又因为求的是前缀,可以用\(Tire\)树维护。
注意到各节点字符串是有重复的。为了节省空间,可以把\(Tire\)树可持久化。
然后就完事了。
其实我一开始做这题时不知道怎么把字符串作为边权。。。
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
#define re register
#define il inline
#define ls x<<1
#define rs x<<1|1
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int N=1e5+100;
int n,q,h[N],cnt,sz[N],son[N],f[N],top[N],d[N],rt[N*100],tot;
struct Tire{int son[26],w;}t[N*60];
struct Edge{int to,nxt;char *s;}e[N<<1];
il void add(re int u,re int v,re char *s){e[++cnt]=(Edge){v,h[u],s};h[u]=cnt;}
char op[N][15];
il ll gi()
{
re ll x=0,t=1;
re char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') t=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*t;
}
il void Insert(re int &u,re char *s,re int x,re int n)
{
t[++tot]=t[u];u=tot;++t[u].w;
if(x>n) return;
Insert(t[u].son[s[x]-'a'],s,x+1,n);
}
il ll Query(re int u,re char *s,re int n)
{
fp(i,1,n) u=t[u].son[s[i]-'a'];
return t[u].w;
}
il void dfs1(re int u,re int fa)
{
f[u]=fa;sz[u]=1;d[u]=d[fa]+1;
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to;
if(v==fa) continue;
Insert(rt[v]=rt[u],e[i].s,1,strlen(e[i].s+1));
dfs1(v,u);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]]) son[u]=v;
}
}
il void dfs2(re int u,re int up)
{
top[u]=up;
if(son[u]) dfs2(son[u],up);
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to;
if(v==f[u]||v==son[u]) continue;
dfs2(v,v);
}
}
il int getLCA(re int u,re int v)
{
while(top[u]^top[v])
{
if(d[top[u]]<d[top[v]]) swap(u,v);
u=f[top[u]];
}
return d[u]<d[v]?u:v;
}
int main()
{
memset(h,-1,sizeof(h));
n=gi();
fp(i,1,n-1)
{
re int u=gi(),v=gi();scanf("%s",op[i]+1);
add(u,v,op[i]);add(v,u,op[i]);
}
dfs1(1,0);dfs2(1,1);
q=gi();
while(q--)
{
re int u=gi(),v=gi(),lca=getLCA(u,v);scanf("%s",op[0]+1);
re int len=strlen(op[0]+1);
printf("%lld\n",Query(rt[u],op[0],len)+Query(rt[v],op[0],len)-2*Query(rt[lca],op[0],len));
}
return 0;
}
[Jsoi2015]字符串树的更多相关文章
- 【BZOJ4477】[JSOI2015]字符串树(Trie树)
[BZOJ4477][JSOI2015]字符串树(Trie树) 题面 BZOJ 题解 对于每个点维护其到根节点的所有字符串构成的\(Trie\),显然可持久化一下就很好写了. 然后每次询问就是\(u+ ...
- BZOJ4477[Jsoi2015]字符串树——可持久化trie树
题目描述 萌萌买了一颗字符串树的种子,春天种下去以后夏天就能长出一棵很大的字符串树.字符串树很奇特,树枝上都密密麻麻写满了字符串,看上去很复杂的样子.[问题描述]字符串树本质上还是一棵树,即N个节点N ...
- luogu P6088 [JSOI2015]字符串树 可持久化trie 线段树合并 树链剖分 trie树
LINK:字符串树 先说比较简单的正解.由于我没有从最简单的考虑答案的角度思考 所以... 下次还需要把所有角度都考察到. 求x~y的答案 考虑 求x~根+y~根-2*lca~根的答案. 那么问题变成 ...
- BZOJ4477: [Jsoi2015]字符串树
[传送门:BZOJ4477] 简要题意: 给出一棵n个点的树,树上的边都代表一个字符串,给出Q个询问,每个询问输入x,y和字符串s,求出x到y的路径上以s为前缀的字符串个数 题解: 自己yy了一波可持 ...
- [bzoj4477 Jsoi2015]字符串树 (可持久化trie)
传送门 Solution 复习下tire( ̄▽ ̄)/ 裸的可持久化tire,我用树剖求了下LCA Code #include <cstdio> #include <cstring&g ...
- BZOJ 4477: [Jsoi2015]字符串树 可持久化trie树
这个是真——可持久化字典树..... code: #include <bits/stdc++.h> #define N 100006 #define setIO(s) freopen(s& ...
- BZOJ4477 JSOI2015字符串树(可持久化trie)
树上建可持久化trie即可,有点过于裸了.darkbzoj过了然而在bzoj一直wa,不知道哪有锅. #include<iostream> #include<cstdio> # ...
- 「JSOI2015」字符串树
「JSOI2015」字符串树 传送门 显然可以树上差分. 我们对于树上每一条从根出发的路径都开一 棵 \(\text{Trie}\) 树,那么我们就只需要在 \(\text{Trie}\) 树中插入一 ...
- 【BZOJ4598】[Sdoi2016]模式字符串 树分治+hash
[BZOJ4598][Sdoi2016]模式字符串 Description 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每 ...
随机推荐
- Buffer.concat()
Buffer.concat(list[, totalLength]) Node.js FS模块方法速查 list {Array} 需要连接的 Buffer 对象数组 totalLength {Numb ...
- Volume 1. Big Number(uva)
如用到bign类参见大整数加减乘除模板 424 - Integer Inquiry #include <iostream> #include <string> #include ...
- mybatis返回map类型数据空值字段不显示(三种解决方法)
转http://blog.csdn.net/lulidaitian/article/details/70941769 一.查询sql添加每个字段的判断空 IFNULL(rate,'') as rate ...
- <struct、union、enum>差异
关于C++和C的区别 区别最大的是struct,C++中的struct几乎和class一样了,可以有成员函数,而C中的struct只能包含成员变量. enum,union没区别. struct的定义 ...
- idea+Maven+SSM框架增删改查
完整项目结构 1.maven配置文件pom.xml <?xml version="1.0" encoding="UTF-8"?> <!-- L ...
- UVALive 6507 Passwords
Passwords Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVALive. Original ...
- xtu summer individual 5 E - Burning Bridges
Burning Bridges Time Limit: 5000ms Memory Limit: 32768KB This problem will be judged on ZJU. Origina ...
- hdu - 1429 胜利大逃亡(续) (bfs状态压缩)
http://acm.hdu.edu.cn/showproblem.php?pid=1429 终于开始能够做状态压缩的题了,虽然这只是状态压缩里面一道很简单的题. 状态压缩就是用二进制的思想来表示状态 ...
- .net 程序集保护与破解
一.保护方法(强签名.混淆.加壳) 强名称是由程序集的标识加上公钥和数字签名组成的.其中,程序集的标识包括简单文本名称.版本号.区域性信息(如果提供的话).语言文化信息.处理器架构信息.强名称是使用相 ...
- DTRACE简介(2)
By samwan on 三月 21, 2007 通过上一次的介绍,相信大家对DTRACE已经有了一个初步的认识.上一次结束时专门留了一个例子,可能大家第一次看有很多不明白的地方,没有关系,随着我们对 ...