[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,其中每 ...
随机推荐
- 集训第四周(高效算法设计)D题 (区间覆盖问题)
原题 UVA10020 :http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19688 经典的贪心问题,区间上贪心当然是右区间越 ...
- Quartz.Net 学习之路02 初探Quartz.Net
第二讲:简单的实例,看看Quartz.Net强在哪里? 直接上代码,代码里有注释: using System; using Quartz; using Quartz.Impl; namespace L ...
- BNUOJ 5235 Starship Troopers
Starship Troopers Time Limit: 5000ms Memory Limit: 32768KB This problem will be judged on HDU. Origi ...
- cdq分治入门--BZOJ1492: [NOI2007]货币兑换Cash
n<=100000天,一开始有s块钱,每天股票A价格ai,B价格bi,每天可以做的事情:卖出股票:按A:B=RTi的比例买入股票.问最后的最大收益.股票可以为浮点数,答案保留三位. 用脚指头想想 ...
- 创建Django项目(七)——表单
2013-08-15 19:43:01| 1.URL配置和视图 "blog\urls.py"文件中:添加url(r'write_article/$', 'write ...
- response的作用
response.addCookies(),添加Cookie. response.sendRedirect()页面跳转,客户端跳转.(能够取到request)
- poj —— 1274 The Perfect Stall
The Perfect Stall Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 26274 Accepted: 116 ...
- Model、ModelMap、ModelAndView的使用和区别
1.Model的使用 数据传递:Model是通过addAttribute方法向页面传递数据的: 数据获取:JSP页面可以通过el表达式或C标签库的方法获取数据: return:return返回的是指定 ...
- SVN 资源权限管理系统 SVNAdmin
原文:https://www.oschina.net/p/svn-admin
- SAS编程基础 - 菜鸟入门常用操作
1. SAS9.4添加和取消注释的快捷键? Ctrl+/:添加注释 Ctrl+Shift+/:取消注释 2. 如何强制终止程序运行? 看到那个圆圈里带叹号的图标了吗?没错,就是它 - 中断! 3. 如 ...