「JSOI2015」字符串树

传送门

显然可以树上差分。

我们对于树上每一条从根出发的路径都开一 棵 \(\text{Trie}\) 树,那么我们就只需要在 \(\text{Trie}\) 树中插入一个字符串时把经过的节点都加 \(1\) 就好了,但是直接开空间会炸掉所以加一个可持久化。

还有一个小问题:我们读入的时候,如果用 char* 来存一条边上的字符串,那么每次都要用不同的 char[] 来传值,不然你就会发现每次的边的值都没变,可能是指针的一些原因吧。

#include <cstring>
#include <cstdio>
#define rg register
#define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
template < class T > inline void swap(T& a, T& b) { T t = a; a = b; b = t; }
template < class T > inline void read(T& s) {
s = 0; int f = 0; char c = getchar();
while ('0' > c || c > '9') f |= c == '-', c = getchar();
while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
s = f ? -s : s;
} const int _ = 1e5 + 5; char s[_][15]; int tot, head[_]; struct Edge { int v, nxt; char* s; } edge[_ << 1];
inline void Add_edge(int u, int v, char* s) { edge[++tot] = (Edge) { v, head[u], s }, head[u] = tot; } int n, m, dep[_], siz[_], son[_], fa[_], top[_];
int tt, rt[_]; struct node { int val, son[26]; } t[_ << 5]; inline void insert(int& p, int q, int x, int len, char* s) {
t[p = ++tt] = t[q], ++t[p].val;
if (x <= len) insert(t[p].son[s[x] - 'a'], t[q].son[s[x] - 'a'], x + 1, len, s);
} inline int query(int p, char* s) {
int len = strlen(s + 1);
for (rg int i = 1; i <= len; ++i) p = t[p].son[s[i] - 'a'];
return t[p].val;
} inline void dfs(int u, int f) {
dep[u] = dep[f] + 1, fa[u] = f, siz[u] = 1;
for (rg int i = head[u]; i; i = edge[i].nxt) {
int v = edge[i].v; if (v == f) continue ;
insert(rt[v], rt[u], 1, strlen(edge[i].s + 1), edge[i].s);
dfs(v, u), siz[u] += siz[v];
if (siz[son[u]] < siz[v]) son[u] = v;
}
} inline void dfs(int u, int f, int topf) {
top[u] = topf;
if (son[u]) dfs(son[u], u, topf);
for (rg int i = head[u]; i; i = edge[i].nxt) {
int v = edge[i].v; if (v == f || v == son[u]) continue ;
dfs(v, u, v);
}
} inline int LCA(int x, int y) {
int fx = top[x], fy = top[y];
while (fx != fy) {
if (dep[fx] < dep[fy]) swap(x, y), swap(fx, fy);
x = fa[fx], fx = top[x];
}
return dep[x] < dep[y] ? x : y;
} int main() {
#ifndef ONLINE_JUDGE
file("cpp");
#endif
read(n);
for (rg int u, v, i = 1; i < n; ++i)
read(u), read(v), scanf("%s", s[i] + 1), Add_edge(u, v, s[i]), Add_edge(v, u, s[i]);
dfs(1, 0), dfs(1, 0, 1);
read(m);
for (rg int u, v; m--; ) {
read(u), read(v), scanf("%s", s[0] + 1);
printf("%d\n", query(rt[u], s[0]) + query(rt[v], s[0]) - 2 * query(rt[LCA(u, v)], s[0]));
}
return 0;
}

「JSOI2015」字符串树的更多相关文章

  1. 「JSOI2015」isomorphism

    「JSOI2015」isomorphism 传送门 我们还是考虑树哈希来判同构. 但是我们需要使用一些特殊的手段来特殊对待假节点. 由于是无向树,我们首先求出重心,然后以重心为根跑树哈希. 此处我们不 ...

  2. 「JSOI2015」非诚勿扰

    「JSOI2015」非诚勿扰 传送门 我们首先考虑一名女性选中她列表里第 \(x\) 名男性的概率(假设她列表里共有 \(s\) 名男性): \[ P = p \times (1 - p) ^ {x ...

  3. 「SHOI2014」三叉神经树 解题报告

    「SHOI2014」三叉神经树 膜拜神仙思路 我们想做一个类似于动态dp的东西,首先得确保我们的运算有一个交换律,这样我们可以把一长串的运算转换成一块一块的放到矩阵上之类的东西,然后拿数据结构维护. ...

  4. 「模板」 线段树——区间乘 && 区间加 && 区间求和

    「模板」 线段树--区间乘 && 区间加 && 区间求和 原来的代码太恶心了,重贴一遍. #include <cstdio> int n,m; long l ...

  5. Loj #2570. 「ZJOI2017」线段树

    Loj #2570. 「ZJOI2017」线段树 题目描述 线段树是九条可怜很喜欢的一个数据结构,它拥有着简单的结构.优秀的复杂度与强大的功能,因此可怜曾经花了很长时间研究线段树的一些性质. 最近可怜 ...

  6. 【LOJ】#3095. 「SNOI2019」字符串

    LOJ#3095. 「SNOI2019」字符串 如果两个串\(i,j\)比较\(i < j\),如果离\(a_{i}\)最近的不同的数是\(a_{k}\),如果\(j < k\)那么\(i ...

  7. 【LOJ】#3043. 「ZJOI2019」线段树

    LOJ#3043. 「ZJOI2019」线段树 计数转期望的一道好题-- 每个点设两个变量\(p,q\)表示这个点有\(p\)的概率有标记,有\(q\)的概率到祖先的路径上有个标记 被覆盖的点$0.5 ...

  8. 【LOJ】#2983. 「WC2019」数树

    LOJ2983. 「WC2019」数树 task0 有\(i\)条边一样答案就是\(y^{n - i}\) task1 这里有个避免容斥的方法,如果有\(i\)条边重复我们要算的是\(y^{n - i ...

  9. 「ZJOI2019」线段树 解题报告

    「ZJOI2019」线段树 听说有人喷这个题简单,然后我就跑去做,然后自闭感++,rp++(雾) 理性分析一波,可以发现最后形成的\(2^k\)个线段树,对应的操作的一个子集,按时间顺序作用到这颗线段 ...

随机推荐

  1. Python3标准库:textwrap文本自动换行与填充

    1. textwrap文本自动换行与填充 textwrap模块提供了一些快捷函数,以及可以完成所有工作的类TextWrapper.如果你只是要对一两个文本字符串进行自动或填充,快捷函数应该就够用了:否 ...

  2. Linux, Nginx - Deepin linux手动安装nginx和出现的问题

    安装步骤 切换至root su 安装依赖库 sudo apt-get install build-essential && sudo apt-get install libtool s ...

  3. css和js处理隔行换色的问题

      <html> <head> <meta charset="utf-8"> <meta name="" conten ...

  4. 浏览器的主要构成High Level Structure

    浏览器的主要组件包括: 1.     用户界面- 包括地址栏.后退/前进按钮.书签目录等,也就是你所看到的除了用来显示你所请求页面的主窗口之外的其他部分 2.     浏览器引擎- 用来查询及操作渲染 ...

  5. 【资源分享】Gmod自由移动镜头脚本

    *----------------------------------------------[下载区]----------------------------------------------* ...

  6. 每天进步一点点------ORCAD Capture CIS

    ORCAD Capture CIS 一.建工程及设置 1.选主菜单 file->new->project ;弹出 project wizard 对话框,取名Myproject : Mypr ...

  7. 安装Oracle进行先决条件检查时显示 Environment variable:"PATH" 失败”

    问题已解决:安装时exe可执行文件的目录也不能有中文,安装时注意目录一定要按oracle的格式.运行安装程序时,要用右键--> 要以管理员方式启动. 原文: 用到oracle数据库,由于电脑装的 ...

  8. servlet常用对象

    Cookie对象 浏览器缓存技术,只存储在浏览器中 cookie的大小在4kb左右,每个浏览器在同一域名下能存放cookie数量是有限的 优缺点:提高网页的效率,减轻服务器的负载;安全性较差. 1 创 ...

  9. MomentJS记录下开发中用到的日期

    1.计算当前周一到周日的日期 ​​​​​​​var weekOfday = moment().format('E');//计算今天是这周第几天 var last_monday = moment().s ...

  10. cef源码分析之cefsimple

    下面是cefsimple的入口代码,主要分成两个部分 // Entry point function for all processes. int APIENTRY wWinMain(HINSTANC ...