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]字符串树的更多相关文章

  1. 【BZOJ4477】[JSOI2015]字符串树(Trie树)

    [BZOJ4477][JSOI2015]字符串树(Trie树) 题面 BZOJ 题解 对于每个点维护其到根节点的所有字符串构成的\(Trie\),显然可持久化一下就很好写了. 然后每次询问就是\(u+ ...

  2. BZOJ4477[Jsoi2015]字符串树——可持久化trie树

    题目描述 萌萌买了一颗字符串树的种子,春天种下去以后夏天就能长出一棵很大的字符串树.字符串树很奇特,树枝上都密密麻麻写满了字符串,看上去很复杂的样子.[问题描述]字符串树本质上还是一棵树,即N个节点N ...

  3. luogu P6088 [JSOI2015]字符串树 可持久化trie 线段树合并 树链剖分 trie树

    LINK:字符串树 先说比较简单的正解.由于我没有从最简单的考虑答案的角度思考 所以... 下次还需要把所有角度都考察到. 求x~y的答案 考虑 求x~根+y~根-2*lca~根的答案. 那么问题变成 ...

  4. BZOJ4477: [Jsoi2015]字符串树

    [传送门:BZOJ4477] 简要题意: 给出一棵n个点的树,树上的边都代表一个字符串,给出Q个询问,每个询问输入x,y和字符串s,求出x到y的路径上以s为前缀的字符串个数 题解: 自己yy了一波可持 ...

  5. [bzoj4477 Jsoi2015]字符串树 (可持久化trie)

    传送门 Solution 复习下tire( ̄▽ ̄)/ 裸的可持久化tire,我用树剖求了下LCA Code #include <cstdio> #include <cstring&g ...

  6. BZOJ 4477: [Jsoi2015]字符串树 可持久化trie树

    这个是真——可持久化字典树..... code: #include <bits/stdc++.h> #define N 100006 #define setIO(s) freopen(s& ...

  7. BZOJ4477 JSOI2015字符串树(可持久化trie)

    树上建可持久化trie即可,有点过于裸了.darkbzoj过了然而在bzoj一直wa,不知道哪有锅. #include<iostream> #include<cstdio> # ...

  8. 「JSOI2015」字符串树

    「JSOI2015」字符串树 传送门 显然可以树上差分. 我们对于树上每一条从根出发的路径都开一 棵 \(\text{Trie}\) 树,那么我们就只需要在 \(\text{Trie}\) 树中插入一 ...

  9. 【BZOJ4598】[Sdoi2016]模式字符串 树分治+hash

    [BZOJ4598][Sdoi2016]模式字符串 Description 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每 ...

随机推荐

  1. win10下硬盘安装CentOS7

    安装环境: 1.系统:Windows 10 2.硬盘:SSD(已装好Win 10) + HHD(用来装CentOS 7) 准备工作: 1.DiskGenius(分区工具):用来给硬盘做分区: 2.系统 ...

  2. Python之机器学习-波斯顿房价预测

    目录 波士顿房价预测 导入模块 获取数据 打印数据 特征选择 散点图矩阵 关联矩阵 训练模型 可视化 波士顿房价预测 导入模块 import pandas as pd import numpy as ...

  3. web前端开发——css

    一.css介绍 1.css是什么? Cascading Style Sheets缩写,层叠样式表.样式定义如何显示HTML元素,样式通常又会存在于样式表中. 2.为什么需要css? 使HTML页面变得 ...

  4. Lucene_Hello(示例)

    (1)创建project (2)导入Lucene的核心包 (3)编写代码建立索引 /lucene01/src/cn/hk/lucene/TestIndex.java: package cn.hk.lu ...

  5. C51 动态数码管 个人笔记

    8段led管构成一个数字. 开发板上共有8个数字. 每个数字有一个使能端(段选引脚) 每个数字的位选端(选择8段led管哪些亮,即构成什么图案)并联在一起 轮流点亮不同数字,速度很快,视觉暂留,从而形 ...

  6. xcap发包工具的简单使用1(构造报文)

    xcap是一个免费的网络发包工具,可以构造和发送常用的网络报文,如arp,ip,icmp,udp等,支持构造报文和发送报文等. 报文隶属于报文组,每个报文组包含多个报文,因此,创建报文首先要创建报文组 ...

  7. Springboot和SpringMVC区别

    Springboot和SpringMVC区别----http://www.cnblogs.com/xdyixia/p/9279644.html

  8. es6常用语法和特性

    简介 首先,在学习之前推荐使用在线转码器 Traceur 来测试 Demo,避免 babel 下的繁琐配置,从而产生畏难情绪. let 命令 在 ES6 之前,JS 只能使用 var 声明变量,或者省 ...

  9. msp430入门编程04

    msp430中C语言的变量与数据类型 msp430入门学习 msp430入门编程

  10. hdu_1398_Square Coins_201404260953

    Square Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...